├── Emitter_Abstract.h ├── Emitter_Fire.cpp ├── Emitter_Fire.h ├── Emitter_Fixed.cpp ├── Emitter_Fixed.h ├── Emitter_Fountain.cpp ├── Emitter_Fountain.h ├── Emitter_Side.cpp ├── Emitter_Side.h ├── Emitter_Spin.cpp ├── Emitter_Spin.h ├── FastLEDRenderer.cpp ├── FastLEDRenderer.h ├── ParticleSys.cpp ├── ParticleSys.h ├── ParticleSysConfig.cpp ├── ParticleSysConfig.h ├── Particle_Abstract.h ├── Particle_Attractor.cpp ├── Particle_Attractor.h ├── Particle_Bounce.cpp ├── Particle_Bounce.h ├── Particle_Fixed.cpp ├── Particle_Fixed.h ├── Particle_Std.cpp ├── Particle_Std.h ├── examples ├── FlameFastLED │ └── FlameFastLED.ino ├── GreenFireFastLED │ └── GreenFireFastLED.ino ├── MultiFlameFastLED │ └── MultiFlameFastLED.ino ├── PainterFastLED │ └── PainterFastLED.ino ├── SmokerFastLED │ └── SmokerFastLED.ino ├── SpinFastLED │ └── SpinFastLED.ino └── StarfieldFastLED │ └── StarfieldFastLED.ino └── readme.md /Emitter_Abstract.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Emitter_Abstract.h - an abstract emitter class 12 | */ 13 | 14 | #ifndef emitter_abstract_h 15 | #define emitter_abstract_h 16 | 17 | #include 18 | #include "Particle_Abstract.h" 19 | 20 | class Emitter_Abstract { 21 | public: 22 | virtual void emit(Particle_Abstract *particle, ParticleSysConfig *g); 23 | virtual void update(ParticleSysConfig *g){} 24 | }; 25 | 26 | #endif /* emitter_abstract_h */ 27 | -------------------------------------------------------------------------------- /Emitter_Fire.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Emitter_Fire.cpp - emit particles to simulate fire 12 | */ 13 | 14 | #include "Emitter_Fire.h" 15 | 16 | uint8_t Emitter_Fire::baseHue = 128; //blues 17 | uint8_t Emitter_Fire::maxTtl = 128; 18 | 19 | Emitter_Fire::Emitter_Fire() 20 | { 21 | counter = 0; 22 | cycleHue = false; 23 | } 24 | 25 | void Emitter_Fire::update(ParticleSysConfig *g) 26 | { 27 | } 28 | 29 | void Emitter_Fire::emit(Particle_Abstract *particle, ParticleSysConfig *g) 30 | { 31 | counter++; 32 | if (cycleHue) baseHue = (counter>>2)%240; 33 | 34 | if ((counter & 0x01) == 0) { 35 | particle->x = random(g->max_x/4, 3 * (g->max_x/4)); 36 | switch (map(particle->x, 0, g->max_x, 0, 9)) { // map value of x from full range to range of 0-8 37 | case 0: 38 | case 7: 39 | particle->ttl = random(1, 7); 40 | break; 41 | case 1: 42 | case 6: 43 | particle->ttl = random(5, 14); 44 | break; 45 | case 2: 46 | case 5: 47 | particle->ttl = random(15, 21); 48 | break; 49 | case 3: 50 | case 4: 51 | particle->ttl = random(25, 28); 52 | break; 53 | } 54 | particle->hue = baseHue+16; 55 | } else { 56 | particle->x = random(g->res_x,g->max_x-g->res_x); 57 | switch (map(particle->x, 0, g->max_x, 0, 9)) { // map value of x from full range to range of 0-8 58 | case 0: 59 | case 7: 60 | particle->ttl = random(1, 20); 61 | break; 62 | case 1: 63 | case 6: 64 | particle->ttl = random(5, 40); 65 | break; 66 | case 2: 67 | case 5: 68 | particle->ttl = random(20, 70); 69 | break; 70 | case 3: 71 | case 4: 72 | particle->ttl = random(40, 100); 73 | break; 74 | } 75 | particle->hue = baseHue; 76 | } 77 | 78 | particle->y = g->max_y-1; 79 | 80 | particle->vx = 0; 81 | particle->vy = 0; 82 | 83 | 84 | particle->isAlive = true; 85 | } 86 | -------------------------------------------------------------------------------- /Emitter_Fire.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Emitter_Fire.h - emit particles to simulate fire 12 | */ 13 | 14 | #ifndef emitter_fire_h 15 | #define emitter_fire_h 16 | 17 | #include "Emitter_Abstract.h" 18 | #include 19 | 20 | class Emitter_Fire : public Emitter_Abstract { 21 | public: 22 | static uint8_t baseHue; 23 | static uint8_t maxTtl; 24 | uint16_t counter; 25 | uint8_t cycleHue; 26 | 27 | Emitter_Fire(); 28 | void emit(Particle_Abstract *particle, ParticleSysConfig *g); 29 | void update(ParticleSysConfig *g); 30 | }; 31 | 32 | #endif /* emitter_fire_h */ 33 | -------------------------------------------------------------------------------- /Emitter_Fixed.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Emitter_Fixed.cpp - emit a particle with the same parameters each time 12 | */ 13 | 14 | #include "Emitter_Fixed.h" 15 | 16 | Emitter_Fixed::Emitter_Fixed(uint16_t x, uint16_t y, int16_t vx, int16_t vy, byte ttl) 17 | { 18 | counter = 0; 19 | this->x = x; 20 | this->y = y; 21 | this->vx = vx; 22 | this->vy = vy; 23 | this->ttl = ttl; 24 | } 25 | 26 | void Emitter_Fixed::emit(Particle_Abstract *particle, ParticleSysConfig *g) 27 | { 28 | counter++; 29 | 30 | particle->vx = vx; 31 | particle->vy = vy; 32 | 33 | particle->x = x; 34 | particle->y = y; 35 | 36 | particle->ttl = ttl; 37 | particle->hue = counter%250; 38 | particle->isAlive = true; 39 | } 40 | -------------------------------------------------------------------------------- /Emitter_Fixed.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Emitter_Fixed.h - emit a particle with the same parameters each time 12 | */ 13 | 14 | #ifndef emitter_fixed_h 15 | #define emitter_fixed_h 16 | 17 | #include "Emitter_Abstract.h" 18 | #include 19 | 20 | class Emitter_Fixed : public Emitter_Abstract { 21 | public: 22 | unsigned int counter; 23 | uint16_t x; 24 | uint16_t y; 25 | int16_t vx; 26 | int16_t vy; 27 | byte ttl; 28 | 29 | Emitter_Fixed(uint16_t x, uint16_t y, int16_t vx, int16_t vy, byte ttl); 30 | void emit(Particle_Abstract *particle, ParticleSysConfig *g); 31 | }; 32 | 33 | #endif /* emitter_fixed_h */ 34 | -------------------------------------------------------------------------------- /Emitter_Fountain.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Emitter_Fountain.cpp - a fountain of particles 12 | */ 13 | 14 | #include "Emitter_Fountain.h" 15 | 16 | byte Emitter_Fountain::minLife = 50; 17 | byte Emitter_Fountain::maxLife = 250; 18 | 19 | Emitter_Fountain::Emitter_Fountain(int16_t vx, int16_t vy, byte var, Particle_Abstract *source) 20 | { 21 | this->vx = vx; 22 | this->vy = vy; 23 | this->var = var; 24 | this->_hVar = (var>>1); 25 | this->source = source; 26 | _constVel = 0; 27 | counter = 0; 28 | 29 | } 30 | Emitter_Fountain::Emitter_Fountain(uint16_t constVel, Particle_Abstract *source) 31 | { 32 | this->vx = 0; 33 | this->vy = 0; 34 | this->var = 0; 35 | if(constVel > 32767) { constVel = 32767; } 36 | _constVel = constVel; 37 | this->_hVar = (_constVel<<1); 38 | this->source = source; 39 | counter = 0; 40 | } 41 | 42 | void Emitter_Fountain::update(ParticleSysConfig *g) 43 | { 44 | source->update(g); 45 | } 46 | 47 | void Emitter_Fountain::emit(Particle_Abstract *particle, ParticleSysConfig *g) 48 | { 49 | counter++; 50 | source->update(g); 51 | 52 | particle->x = source->x; 53 | particle->y = source->y; 54 | if(_constVel > 0) { 55 | particle->vx = random(_hVar)-_constVel; 56 | particle->vy = sqrt(pow(_constVel,2)-pow(particle->vx,2)); 57 | if(random(8)<3) { particle->vy=-particle->vy; } 58 | } else { 59 | particle->vx = vx + random(var)-_hVar; 60 | particle->vy = vy + random(var)-_hVar; 61 | } 62 | particle->ttl = random(minLife, maxLife); 63 | particle->hue = (counter/2)%255; 64 | particle->isAlive = true; 65 | } 66 | -------------------------------------------------------------------------------- /Emitter_Fountain.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Emitter_Fountain.h - a fountain of particles 12 | */ 13 | 14 | #ifndef emitter_fountain_h 15 | #define emitter_fountain_h 16 | 17 | #include "Emitter_Abstract.h" 18 | #include "Particle_Abstract.h" 19 | #include 20 | 21 | class Emitter_Fountain : public Emitter_Abstract { 22 | public: 23 | static byte minLife; 24 | static byte maxLife; 25 | int16_t vx; //horizontal velocity for emitted particles 26 | int16_t vy; //vertical velocity for emitted particles 27 | byte var; //emitted particles velocity variance 28 | Particle_Abstract *source; //source point 29 | unsigned int counter; 30 | 31 | Emitter_Fountain(int16_t vx, int16_t vy, byte var, Particle_Abstract *source); 32 | Emitter_Fountain(uint16_t constVel, Particle_Abstract *source); 33 | void emit(Particle_Abstract *particle, ParticleSysConfig *g); 34 | void update(ParticleSysConfig *g); 35 | private: 36 | uint16_t _hVar; 37 | uint16_t _constVel; 38 | }; 39 | 40 | #endif /* emitter_fountain_h */ 41 | -------------------------------------------------------------------------------- /Emitter_Side.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Emitter_Side.cpp - emit particles from one side of the box 12 | */ 13 | 14 | #include "Emitter_Side.h" 15 | 16 | byte Emitter_Side::baseHue = 128; //blues 17 | byte Emitter_Side::maxTtl = 128; 18 | 19 | Emitter_Side::Emitter_Side(char side) 20 | { 21 | counter = 0; 22 | this->side = side; 23 | this->minVelocity = 1; 24 | this->maxVelocity = 4; 25 | } 26 | Emitter_Side::Emitter_Side(char side, uint8_t minVelocity, uint8_t maxVelocity) { 27 | counter = 0; 28 | this->side = side; 29 | this->minVelocity = minVelocity; 30 | this->maxVelocity = maxVelocity; 31 | } 32 | 33 | void Emitter_Side::emit(Particle_Abstract *particle, ParticleSysConfig *g) 34 | { 35 | counter++; 36 | 37 | switch(side) { 38 | case 'b': 39 | particle->x = random(g->max_x); 40 | particle->y = g->max_y-g->res_y; 41 | particle->vx = 0; 42 | particle->vy = random(-maxVelocity,(-minVelocity)+1); 43 | break; 44 | case 'r': 45 | particle->x = g->max_x-g->res_x; 46 | particle->y = random(g->max_y); 47 | particle->vx = random(-maxVelocity,(-minVelocity)+1); 48 | particle->vy = 0; 49 | break; 50 | case 't': 51 | particle->x = random(g->max_x); 52 | particle->y = 1; 53 | particle->vx = 0; 54 | particle->vy = random(minVelocity,maxVelocity+1); 55 | break; 56 | case 'l': 57 | particle->x = 1; 58 | particle->y = random(g->max_y); 59 | particle->vx = random(minVelocity,maxVelocity+1); 60 | particle->vy = 0; 61 | break; 62 | } 63 | 64 | particle->ttl = random(1, maxTtl); 65 | particle->hue = baseHue; 66 | particle->isAlive = true; 67 | } 68 | -------------------------------------------------------------------------------- /Emitter_Side.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Emitter_Side.h - emit particles from one side of the box 12 | */ 13 | 14 | #ifndef emitter_side_h 15 | #define emitter_side_h 16 | 17 | #include "Emitter_Abstract.h" 18 | #include 19 | 20 | class Emitter_Side : public Emitter_Abstract { 21 | public: 22 | static byte baseHue; 23 | static byte maxTtl; 24 | unsigned int counter; 25 | char side; 26 | uint8_t minVelocity; 27 | uint8_t maxVelocity; 28 | 29 | Emitter_Side(char side); 30 | Emitter_Side(char side, uint8_t minVelocity, uint8_t maxVelocity); 31 | void emit(Particle_Abstract *particle, ParticleSysConfig *g); 32 | }; 33 | 34 | #endif /* emitter_side_h */ 35 | -------------------------------------------------------------------------------- /Emitter_Spin.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Emitter_Spin.cpp - a spinning emitter 12 | */ 13 | 14 | #include "Emitter_Spin.h" 15 | 16 | byte Emitter_Spin::maxTtl = 100; 17 | 18 | Emitter_Spin::Emitter_Spin(uint16_t x, uint16_t y, uint16_t r, int16_t rv) 19 | { 20 | this->x = x; 21 | this->y = y; 22 | this->r = r; 23 | this->rv = tempRv = rv; 24 | oscilate = false; 25 | counter = 0; 26 | } 27 | Emitter_Spin::Emitter_Spin(ParticleSysConfig *g, uint16_t r, int16_t rv) { 28 | this->x = g->center_x; // default position at center of particle system 29 | this->y = g->center_y; 30 | this->r = r; 31 | this->rv = tempRv = rv; 32 | oscilate = false; 33 | counter = 0; 34 | } 35 | 36 | void Emitter_Spin::update(ParticleSysConfig *g) 37 | { 38 | static signed char direction = -1; 39 | float radAngle; 40 | counter++; 41 | 42 | //calculate velocity vector 43 | if (oscilate && (counter%20 == 0)){ 44 | tempRv += direction; 45 | if (abs(tempRv) > rv){ 46 | direction = -direction; 47 | } 48 | } 49 | 50 | // Conver from Degree -> Rad 51 | if (counter%2 == 0) { 52 | radAngle = -counter*tempRv*(PI/180) ; 53 | } else { 54 | radAngle = 180-counter*tempRv*(PI/180) ; 55 | } 56 | // Convert Polar -> Cartesian 57 | vx = (int16_t)(r * cos(radAngle)); 58 | vy = (int16_t)(r * sin(radAngle)); 59 | } 60 | 61 | void Emitter_Spin::emit(Particle_Abstract *particle, ParticleSysConfig *g) 62 | { 63 | particle->x = this->x; 64 | particle->y = this->y; 65 | 66 | particle->vx = vx; 67 | particle->vy = vy; 68 | 69 | particle->ttl = random(20, maxTtl); 70 | particle->hue = (counter>>1)%255; 71 | particle->isAlive = true; 72 | } 73 | -------------------------------------------------------------------------------- /Emitter_Spin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Emitter_Spin.h - a spinning emitter 12 | * works well with 36 particles 13 | */ 14 | 15 | #ifndef emitter_spin_h 16 | #define emitter_spin_h 17 | 18 | #include "Emitter_Abstract.h" 19 | #include 20 | 21 | class Emitter_Spin : public Emitter_Abstract { 22 | public: 23 | static byte maxTtl; 24 | uint16_t x; //left 25 | uint16_t y; //bottom 26 | uint16_t r; //radius 27 | int16_t rv; //radial velocity 28 | boolean oscilate; //whether to oscilate radial velocity 29 | unsigned int counter; 30 | Emitter_Spin(uint16_t x, uint16_t y, uint16_t r, int16_t rv); 31 | Emitter_Spin(ParticleSysConfig *g, uint16_t r, int16_t rv); 32 | void emit(Particle_Abstract *particle, ParticleSysConfig *g); 33 | void update(ParticleSysConfig *g); 34 | private: 35 | int16_t vx; 36 | int16_t vy; 37 | int16_t tempRv; 38 | }; 39 | 40 | #endif /* emitter_spin_h */ 41 | -------------------------------------------------------------------------------- /FastLEDRenderer.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* Adaptation for FastLED by Gottfried Mayer github.com/fuse314 */ 11 | 12 | /* 13 | * FastLEDRenderer.cpp renders a particle system to an RGB matrix 14 | * Params: 15 | * left/top: origin point on LED matrix to start rendering the particle system 16 | * width/height: width and height of "window" to particle system to render 17 | * crop_left/crop_top: origin point in particle system to start rendering 18 | * 19 | * see example CroppedPainterFastLED 20 | */ 21 | 22 | #include "FastLEDRenderer.h" 23 | 24 | FastLEDRenderer::FastLEDRenderer(ParticleSysConfig *g) { 25 | init(g, 0, 0, g->width, g->height, 0, 0); 26 | } 27 | FastLEDRenderer::FastLEDRenderer(ParticleSysConfig *g, uint8_t left, uint8_t top, uint8_t width, uint8_t height) { 28 | init(g, left, top, width, height, 0, 0); 29 | } 30 | FastLEDRenderer::FastLEDRenderer(ParticleSysConfig *g, uint8_t left, uint8_t top, uint8_t width, uint8_t height, uint8_t crop_left, uint8_t crop_top) { 31 | init(g, left, top, width, height, crop_left, crop_top); 32 | } 33 | 34 | void FastLEDRenderer::init(ParticleSysConfig *g, uint8_t left, uint8_t top, uint8_t width, uint8_t height, uint8_t crop_left, uint8_t crop_top) { 35 | this->left = left; 36 | this->top = top; 37 | if(width > g->width || width == 0) { width = g->width; } // sanity check for width 38 | if(height > g->height || height == 0) { height = g->height; } // sanity check for height 39 | if(width + crop_left > g->width) { crop_left = 0; } // sanity check for crop_left 40 | if(height + crop_top > g->height) { crop_top = 0; } // sanity check for crop_top 41 | this->width = width; 42 | this->height = height; 43 | this->crop_left = crop_left; 44 | this->crop_top = crop_top; 45 | this->globalBrightness = 255; 46 | } 47 | 48 | /* GMA hier - change below ########################################################## */ 49 | 50 | void FastLEDRenderer::render(ParticleSysConfig *g, Particle_Abstract particles[], byte numParticles, CRGB *_leds) { 51 | byte row, col; 52 | uint16_t dx, dy; 53 | uint8_t tempVal; 54 | CRGB baseRGB; 55 | 56 | //go over particles and update matrix cells on the way 57 | for(int i = 0; i 0 && crop_left * g->res_x > particles[i].x) { // only render if x-position is inside cropped window 62 | continue; 63 | } 64 | if(crop_top > 0 && crop_top * g->res_y > particles[i].y) { // only render if y-position is inside cropped window 65 | continue; 66 | } 67 | uint16_t part_x = particles[i].x - (crop_left * g->res_x); 68 | uint16_t part_y = particles[i].y - (crop_top * g->res_y); 69 | //generate RGB values for particle 70 | baseRGB = CHSV(particles[i].hue, 255,255); 71 | 72 | dx = g->res_x - (part_x % g->res_x); 73 | dy = g->res_y - (part_y % g->res_y); 74 | 75 | //bottom left 76 | col = part_x / g->res_x; 77 | row = part_y / g->res_y; 78 | tempVal = calcTempVal(g,dx,dy,particles[i].ttl); 79 | addColor(col, row, &baseRGB, tempVal, _leds); 80 | 81 | //bottom right; 82 | col++; 83 | if (col < g->width) { 84 | tempVal = calcTempVal(g,(g->res_x-dx),dy,particles[i].ttl); 85 | addColor(col, row, &baseRGB, tempVal, _leds); 86 | } 87 | 88 | //top right 89 | row++; 90 | if (col < g->width && row < g->height) { 91 | tempVal = calcTempVal(g,(g->res_x-dx),(g->res_y-dy),particles[i].ttl); 92 | addColor(col, row, &baseRGB, tempVal, _leds); 93 | } 94 | 95 | //top left 96 | col--; 97 | if (row < g->height) { 98 | tempVal = calcTempVal(g,dx,(g->res_y-dy),particles[i].ttl); 99 | addColor(col, row, &baseRGB, tempVal, _leds); 100 | } 101 | } 102 | } 103 | 104 | uint8_t FastLEDRenderer::calcTempVal(ParticleSysConfig *g, uint16_t dx, uint16_t dy, uint8_t ttl) { 105 | uint8_t _ttl = ttl; 106 | if(globalBrightness < 255) { 107 | _ttl = scale8(_ttl,globalBrightness); 108 | } 109 | unsigned long r = ((unsigned long)dx*dy*_ttl)/g->res_area; 110 | if(r > 255) 111 | return 255; 112 | return r; 113 | } 114 | 115 | void FastLEDRenderer::addColor(byte col, byte row, CRGB *colorRGB, byte value, CRGB *_leds) { 116 | if(col >= width || row >= height) // check if pixel is outside of the render area 117 | return; 118 | // add colorRGB with intensity of value at position (col, row) to the existing RGB value 119 | CRGB newColor = colorRGB[0]; 120 | newColor.fadeToBlackBy(255-value); 121 | _leds[XY(left+col,top+row)] += newColor; 122 | } 123 | 124 | void FastLEDRenderer::reset(CRGB *_leds) { 125 | //init all pixels to black 126 | for(byte y=top; y 22 | 23 | class FastLEDRenderer { 24 | public: 25 | FastLEDRenderer(ParticleSysConfig *g); 26 | FastLEDRenderer(ParticleSysConfig *g, uint8_t left, uint8_t top, uint8_t width, uint8_t height); 27 | FastLEDRenderer(ParticleSysConfig *g, uint8_t left, uint8_t top, uint8_t width, uint8_t height, uint8_t crop_left, uint8_t crop_top); 28 | void render(ParticleSysConfig *g, Particle_Abstract particles[], byte numParticles, CRGB *_leds); 29 | void reset(CRGB *_leds); //set each pixel to 0 30 | void fade(CRGB *_leds); //divide each pixel by half 31 | void fadeBy(byte amount, CRGB *_leds); //substract amount from each pixel 32 | uint8_t globalBrightness; 33 | private: 34 | uint8_t left,top,width,height,crop_left,crop_top; 35 | void init(ParticleSysConfig *g, uint8_t left, uint8_t top, uint8_t width, uint8_t height, uint8_t crop_left, uint8_t crop_top); 36 | void addColor(byte col, byte row, CRGB *rgb, byte value, CRGB *_leds); 37 | uint8_t calcTempVal(ParticleSysConfig *g, uint16_t dx, uint16_t dy, uint8_t ttl); 38 | }; 39 | 40 | // we need to declare this function here, otherwise there are errors while compiling... 41 | extern uint16_t XY(uint8_t x, uint8_t y); 42 | 43 | #endif /* psys_fastled_renderer_h */ -------------------------------------------------------------------------------- /ParticleSys.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * ParticleSys.cpp - generic particle system class 12 | */ 13 | 14 | #include "ParticleSys.h" 15 | 16 | byte ParticleSys::perCycle = 1; 17 | 18 | ParticleSys::ParticleSys(ParticleSysConfig *g, byte numParticles, Particle_Abstract particles[], Emitter_Abstract *emitter) 19 | { 20 | this->g = g; 21 | this->numParticles = numParticles; 22 | this->particles = particles; 23 | this->emitter = emitter; 24 | } 25 | 26 | void ParticleSys::update() 27 | { 28 | cycleRemaining = perCycle; 29 | emitter->update(this->g); 30 | for(byte i=0; i 0) { 32 | emitter->emit(&particles[i], this->g); 33 | cycleRemaining--; 34 | } 35 | if (particles[i].isAlive){ 36 | particles[i].update(this->g); 37 | } 38 | } 39 | } 40 | 41 | -------------------------------------------------------------------------------- /ParticleSys.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * ParticleSys.h - generic particle system class 12 | */ 13 | 14 | #ifndef p_system_h 15 | #define p_system_h 16 | 17 | #include "ParticleSysConfig.h" 18 | #include "Particle_Abstract.h" 19 | #include "Emitter_Abstract.h" 20 | 21 | // use this as the main .h file, so we will include all the .h files of the project 22 | #include "Particle_Attractor.h" 23 | #include "Particle_Bounce.h" 24 | #include "Particle_Fixed.h" 25 | #include "Particle_Std.h" 26 | #include "Emitter_Fire.h" 27 | #include "Emitter_Fixed.h" 28 | #include "Emitter_Fountain.h" 29 | #include "Emitter_Side.h" 30 | #include "Emitter_Spin.h" 31 | #include "FastLEDRenderer.h" 32 | 33 | 34 | class ParticleSys { 35 | public: 36 | static byte perCycle; 37 | ParticleSysConfig *g; 38 | byte numParticles; 39 | Particle_Abstract *particles; 40 | Emitter_Abstract *emitter; 41 | 42 | ParticleSys(ParticleSysConfig *g, byte numParticles, Particle_Abstract particles[], Emitter_Abstract *emitter); 43 | void update(); 44 | 45 | private: 46 | byte cycleRemaining; 47 | }; 48 | 49 | #endif /* p_system_h */ 50 | -------------------------------------------------------------------------------- /ParticleSysConfig.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | #include "ParticleSysConfig.h" 11 | 12 | ParticleSysConfig::ParticleSysConfig(uint8_t width, uint8_t height) { 13 | this->width = width; 14 | this->height = height; 15 | this->res_x = 32; // default resolution 16 | this->res_y = 32; 17 | calcValues(); 18 | } 19 | ParticleSysConfig::ParticleSysConfig(uint8_t width, uint8_t height, uint8_t res_x, uint8_t res_y) { 20 | this->width = width; 21 | this->height = height; 22 | this->res_x = res_x; 23 | this->res_y = res_y; 24 | calcValues(); 25 | } 26 | 27 | void ParticleSysConfig::calcValues(void) { 28 | this->res_area = this->res_x*this->res_y; 29 | this->max_x = (this->width * this->res_x - 1); 30 | this->max_y = (this->height * this->res_y - 1); 31 | this->center_x = (this->max_x/2)-(this->res_x/2); 32 | this->center_y = (this->max_y/2)-(this->res_y/2); 33 | } 34 | -------------------------------------------------------------------------------- /ParticleSysConfig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | #ifndef PS_GLOBALS_T 11 | #define PS_GLOBALS_T 12 | #include 13 | 14 | class ParticleSysConfig { 15 | public: 16 | uint8_t width; 17 | uint8_t height; 18 | uint8_t res_x; 19 | uint8_t res_y; 20 | uint16_t res_area; 21 | uint16_t max_x; 22 | uint16_t max_y; 23 | uint16_t center_x; 24 | uint16_t center_y; 25 | ParticleSysConfig(uint8_t width, uint8_t height); 26 | ParticleSysConfig(uint8_t width, uint8_t height, uint8_t res_x, uint8_t res_y); 27 | private: 28 | void calcValues(void); 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /Particle_Abstract.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * particle.h - abstract particle class 12 | */ 13 | 14 | #ifndef particle_abstract_h 15 | #define particle_abstract_h 16 | 17 | #include "ParticleSysConfig.h" 18 | #include 19 | 20 | class Particle_Abstract { 21 | public: 22 | uint16_t x; //left 23 | uint16_t y; //bottom 24 | int16_t vx; //horizontal velocity 25 | int16_t vy; //vertical velocity 26 | uint8_t ttl; //time to live 27 | uint8_t hue; //hue 28 | uint8_t isAlive; //is alive? 29 | 30 | virtual void update(ParticleSysConfig *g); 31 | }; 32 | 33 | #endif /* particle_abstract_h */ 34 | -------------------------------------------------------------------------------- /Particle_Attractor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Particle_Attractor.cpp - particle with an attractor 12 | */ 13 | 14 | #include "Particle_Attractor.h" 15 | 16 | uint16_t Particle_Attractor::atx = 0; 17 | uint16_t Particle_Attractor::aty = 0; 18 | int16_t Particle_Attractor::atf = 4; 19 | 20 | Particle_Attractor::Particle_Attractor(void) 21 | { 22 | isAlive = 0; 23 | } 24 | Particle_Attractor::Particle_Attractor(uint16_t atx, uint16_t aty) { 25 | this->atx = atx; 26 | this->aty = aty; 27 | isAlive = 0; 28 | } 29 | 30 | void Particle_Attractor::update(ParticleSysConfig *g) 31 | { 32 | int16_t dx, dy, tempX, tempY, tempVx, tempVy; 33 | int16_t acx, acy; 34 | float mult; 35 | 36 | //this particle does not age 37 | 38 | dx = (int16_t)atx - x; 39 | dy = (int16_t)aty - y; 40 | mult = (float)atf/sqrt(dx*dx+dy*dy); 41 | acx = (int16_t)(mult*dx); 42 | acy = (int16_t)(mult*dy); 43 | 44 | //apply acceleration 45 | tempVx = vx+acx; 46 | tempVy = vy+acy; 47 | 48 | tempX = x + tempVx; 49 | tempY = y + tempVy; 50 | 51 | if (tempX < 0 || tempX > g->max_x) { 52 | tempVx = 0; 53 | } 54 | if (tempY < 0 || tempY > g->max_y) { 55 | tempVy = 0; 56 | } 57 | 58 | if (tempVx > 50 || tempVx < -50) { 59 | vx = random(10)-5; 60 | } else { 61 | vx = tempVx; 62 | } 63 | 64 | if (tempVy > 50 || tempVy < -50) { 65 | vy = random(10)-5; 66 | } else { 67 | vy = tempVy; 68 | } 69 | 70 | if (tempX > g->max_x) { 71 | x = g->max_x; 72 | } else if (tempX < 0) { 73 | x = 0; 74 | } else { 75 | x = tempX; 76 | } 77 | 78 | if (tempY > g->max_y) { 79 | y = g->max_y; 80 | } else if (tempY < 0) { 81 | y = 0; 82 | } else { 83 | y = tempY; 84 | } 85 | } 86 | 87 | -------------------------------------------------------------------------------- /Particle_Attractor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Particle_Attractor.h - particle with an attractor 12 | */ 13 | 14 | #ifndef particle_attractor_h 15 | #define particle_attractor_h 16 | 17 | #include "Particle_Abstract.h" 18 | 19 | class Particle_Attractor : public Particle_Abstract { 20 | public: 21 | static uint16_t atx; //horizontal attractor position 22 | static uint16_t aty; //vertical attractor position 23 | static int16_t atf; //attractor force 24 | 25 | Particle_Attractor(void); 26 | Particle_Attractor(uint16_t atx, uint16_t aty); 27 | void update(ParticleSysConfig *g); 28 | }; 29 | 30 | #endif /* particle_attractor_h */ 31 | -------------------------------------------------------------------------------- /Particle_Bounce.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * particle.cpp - a particle that bounces off the "box" walls 12 | */ 13 | 14 | #include "Particle_Bounce.h" 15 | 16 | int16_t Particle_Bounce::ax = 0; 17 | int16_t Particle_Bounce::ay = 0; 18 | 19 | Particle_Bounce::Particle_Bounce() 20 | { 21 | isAlive = 0; 22 | } 23 | 24 | void Particle_Bounce::update(ParticleSysConfig *g) 25 | { 26 | //age 27 | ttl--; 28 | 29 | //apply acceleration 30 | vx = min(vx + ax, g->max_x); 31 | vy = min(vy + ay, g->max_y); 32 | 33 | //apply velocity 34 | if (y == 0 || y >= g->max_y) { 35 | vy = -1 * vy; 36 | } 37 | if (x == 0 || x >= g->max_x) { 38 | vx = -1 * vx; 39 | } 40 | if (ttl == 0 || (vx == 0 && vy == 0)) { 41 | isAlive = 0; 42 | } else { 43 | x = min(max(x + vx, 0), g->max_x); 44 | y = min(max(y + vy, 0), g->max_y); 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /Particle_Bounce.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Particle_Bounce.h - a particle that bounces off the "box" walls 12 | */ 13 | 14 | #ifndef particle_bounce_h 15 | #define particle_bounce_h 16 | 17 | #include "Particle_Abstract.h" 18 | 19 | class Particle_Bounce : public Particle_Abstract { 20 | public: 21 | static int16_t ax; //horizontal acceleration 22 | static int16_t ay; //vertical acceleration 23 | 24 | Particle_Bounce(); 25 | void update(ParticleSysConfig *g); 26 | }; 27 | 28 | #endif /* particle_bounce_h */ 29 | -------------------------------------------------------------------------------- /Particle_Fixed.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Particle_Fixed.cpp - a fixed particle that doen't move, just fades 12 | */ 13 | 14 | #include "Particle_Fixed.h" 15 | 16 | byte Particle_Fixed::decayFactor = 10; 17 | 18 | Particle_Fixed::Particle_Fixed() 19 | { 20 | isAlive = 0; 21 | } 22 | Particle_Fixed::Particle_Fixed(uint16_t x, uint16_t y) { 23 | this->x = x; 24 | this->y = y; 25 | this->vx = 0; 26 | this->vy = 0; 27 | this->isAlive = 0; 28 | } 29 | 30 | void Particle_Fixed::update(ParticleSysConfig *g) 31 | { 32 | //age 33 | if (ttl < decayFactor) { 34 | isAlive = 0; 35 | return; 36 | } 37 | ttl -= decayFactor; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /Particle_Fixed.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Particle_Fixed.h - a fixed particle that doen't move, just fades 12 | */ 13 | 14 | #ifndef particle_fixed_h 15 | #define particle_fixed_h 16 | 17 | #include "Particle_Abstract.h" 18 | 19 | class Particle_Fixed : public Particle_Abstract { 20 | public: 21 | static byte decayFactor; 22 | Particle_Fixed(); 23 | Particle_Fixed(uint16_t x, uint16_t y); 24 | void update(ParticleSysConfig *g); 25 | }; 26 | 27 | #endif /* particle_fixed_h */ 28 | -------------------------------------------------------------------------------- /Particle_Std.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Particle_Std.cpp - standard particle, dies when out of bounds 12 | */ 13 | 14 | #include "Particle_Std.h" 15 | 16 | int16_t Particle_Std::ax = 0; 17 | int16_t Particle_Std::ay = 0; 18 | 19 | Particle_Std::Particle_Std() 20 | { 21 | isAlive = 0; 22 | } 23 | 24 | void Particle_Std::update(ParticleSysConfig *g) 25 | { 26 | //age 27 | ttl--; 28 | 29 | //apply acceleration 30 | vx = min(vx+ax, g->max_x); 31 | vy = min(vy+ay, g->max_y); 32 | 33 | //apply velocity 34 | uint16_t newX, newY; 35 | newX = x + vx; 36 | newY = y + vy; 37 | if(ttl == 0 || newX < 0 || newX > g->max_x || newY < 0 || newY > g->max_y) { 38 | isAlive = 0; 39 | } else { 40 | x = newX; 41 | y = newY; 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /Particle_Std.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * Particle_Std.h - standard particle, dies when out of bounds 12 | */ 13 | 14 | #ifndef particle_std_h 15 | #define particle_std_h 16 | 17 | #include "Particle_Abstract.h" 18 | 19 | class Particle_Std : public Particle_Abstract { 20 | public: 21 | static int16_t ax; //horizontal acceleration 22 | static int16_t ay; //vertical acceleration 23 | 24 | Particle_Std(); 25 | void update(ParticleSysConfig *g); 26 | }; 27 | 28 | #endif /* particle_std_h */ 29 | -------------------------------------------------------------------------------- /examples/FlameFastLED/FlameFastLED.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * An example for the Arduino particle system library 12 | * Creates a color-changing flame 13 | */ 14 | 15 | #include 16 | 17 | #define LED_WIDTH 8 18 | #define LED_HEIGHT 8 19 | 20 | // set ledSerpentineLayout to true if your matrix looks wrong ;) - see Example "XYMatrix" in FastLED library. 21 | const bool ledSerpentineLayout = false; 22 | // translates from x, y into an index into the LED array 23 | uint16_t XY( uint8_t x, uint8_t y) { 24 | if(y >= LED_HEIGHT) { y = LED_HEIGHT - 1; } 25 | if(x >= LED_WIDTH) { x = LED_WIDTH - 1; } 26 | uint16_t ret; 27 | if(ledSerpentineLayout == false) { 28 | ret = (y * LED_WIDTH) + x; 29 | } else { 30 | if( y & 0x01) { 31 | // Odd rows run backwards 32 | uint8_t revX = (LED_WIDTH - 1) - x; 33 | ret = (y * LED_WIDTH) + revX; 34 | } else { 35 | // Even rows run forwards 36 | ret = (y * LED_WIDTH) + x; 37 | } 38 | } 39 | return ret; 40 | } 41 | 42 | // Particle System 43 | 44 | #include 45 | 46 | #define NUM_LEDS (LED_WIDTH * LED_HEIGHT) 47 | #define LED_PIN 7 48 | #define COLOR_ORDER GRB 49 | #define CHIPSET WS2811 50 | #define BRIGHTNESS 32 51 | CRGB leds[ NUM_LEDS ]; 52 | 53 | const byte numParticles = 60; 54 | 55 | ParticleSysConfig g(LED_WIDTH, LED_HEIGHT); 56 | Particle_Std particles[numParticles]; 57 | Particle_Fixed source; 58 | Emitter_Fountain emitter(0, 0, 5, &source); 59 | ParticleSys pSys(&g, numParticles, particles, &emitter); 60 | FastLEDRenderer renderer(&g); 61 | 62 | void setup() { 63 | FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); 64 | FastLED.setBrightness( BRIGHTNESS ); 65 | 66 | randomSeed(analogRead(0)); 67 | 68 | renderer.reset(leds); 69 | 70 | source.x = g.center_x; 71 | source.y = g.max_y-(g.res_y/2); 72 | 73 | Particle_Std::ay = -1; 74 | pSys.perCycle = 10; 75 | emitter.minLife = 20; 76 | emitter.maxLife = 80; 77 | 78 | } 79 | 80 | void loop() { 81 | pSys.update(); 82 | renderer.reset(leds); 83 | renderer.render(&g, particles, numParticles, leds); 84 | FastLED.show(); 85 | delay(30); 86 | } 87 | 88 | -------------------------------------------------------------------------------- /examples/GreenFireFastLED/GreenFireFastLED.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * An example for the Arduino particle system library 12 | * Creates a green fire effect 13 | */ 14 | 15 | #include 16 | 17 | #define LED_WIDTH 8 18 | #define LED_HEIGHT 8 19 | 20 | // set ledSerpentineLayout to true if your matrix looks wrong ;) - see Example "XYMatrix" in FastLED library. 21 | const bool ledSerpentineLayout = false; 22 | // translates from x, y into an index into the LED array 23 | uint16_t XY( uint8_t x, uint8_t y) { 24 | if(y >= LED_HEIGHT) { y = LED_HEIGHT - 1; } 25 | if(x >= LED_WIDTH) { x = LED_WIDTH - 1; } 26 | uint16_t ret; 27 | if(ledSerpentineLayout == false) { 28 | ret = (y * LED_WIDTH) + x; 29 | } else { 30 | if( y & 0x01) { 31 | // Odd rows run backwards 32 | uint8_t revX = (LED_WIDTH - 1) - x; 33 | ret = (y * LED_WIDTH) + revX; 34 | } else { 35 | // Even rows run forwards 36 | ret = (y * LED_WIDTH) + x; 37 | } 38 | } 39 | return ret; 40 | } 41 | 42 | // Particle System 43 | 44 | #include 45 | 46 | #define NUM_LEDS (LED_WIDTH * LED_HEIGHT) 47 | #define LED_PIN 7 48 | #define COLOR_ORDER GRB 49 | #define CHIPSET WS2811 50 | #define BRIGHTNESS 32 51 | CRGB leds[ NUM_LEDS ]; 52 | 53 | const byte numParticles = 60; 54 | 55 | ParticleSysConfig g(LED_WIDTH, LED_HEIGHT); 56 | Particle_Std particles[numParticles]; 57 | Emitter_Fire emitter; 58 | ParticleSys pSys(&g, numParticles, particles, &emitter); 59 | FastLEDRenderer renderer(&g); 60 | 61 | void setup() { 62 | FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); 63 | FastLED.setBrightness( BRIGHTNESS ); 64 | 65 | randomSeed(analogRead(0)); 66 | 67 | renderer.reset(leds); 68 | 69 | Particle_Std::ay = -1; 70 | pSys.perCycle = 10; 71 | emitter.baseHue = 75; // green 72 | // emitter.baseHue = 156; // blue 73 | emitter.maxTtl = 96; 74 | 75 | } 76 | 77 | void loop() { 78 | pSys.update(); 79 | renderer.reset(leds); 80 | renderer.render(&g, particles, numParticles, leds); 81 | FastLED.show(); 82 | delay(30); 83 | } 84 | 85 | -------------------------------------------------------------------------------- /examples/MultiFlameFastLED/MultiFlameFastLED.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * An example for the Arduino particle system library 12 | * example with multiple particle systems, creates multiple flames 13 | */ 14 | 15 | #include 16 | 17 | #define LED_WIDTH 8 18 | #define LED_HEIGHT 8 19 | 20 | // set ledSerpentineLayout to true if your matrix looks wrong ;) - see Example "XYMatrix" in FastLED library. 21 | const bool ledSerpentineLayout = false; 22 | // translates from x, y into an index into the LED array 23 | uint16_t XY( uint8_t x, uint8_t y) { 24 | if(y >= LED_HEIGHT) { y = LED_HEIGHT - 1; } 25 | if(x >= LED_WIDTH) { x = LED_WIDTH - 1; } 26 | uint16_t ret; 27 | if(ledSerpentineLayout == false) { 28 | ret = (y * LED_WIDTH) + x; 29 | } else { 30 | if( y & 0x01) { 31 | // Odd rows run backwards 32 | uint8_t revX = (LED_WIDTH - 1) - x; 33 | ret = (y * LED_WIDTH) + revX; 34 | } else { 35 | // Even rows run forwards 36 | ret = (y * LED_WIDTH) + x; 37 | } 38 | } 39 | return ret; 40 | } 41 | 42 | // Particle System 43 | 44 | #include 45 | 46 | #define NUM_LEDS (LED_WIDTH * LED_HEIGHT) 47 | #define LED_PIN 7 48 | #define COLOR_ORDER GRB 49 | #define CHIPSET WS2811 50 | #define BRIGHTNESS 32 51 | CRGB leds[ NUM_LEDS ]; 52 | 53 | // particle system 1 54 | const byte numParticles = 60; 55 | 56 | ParticleSysConfig g(LED_WIDTH, LED_HEIGHT); 57 | Particle_Std particles[numParticles]; 58 | Particle_Fixed source; 59 | Emitter_Fountain emitter(0, 0, 5, &source); 60 | ParticleSys pSys(&g, numParticles, particles, &emitter); 61 | 62 | // particle system 2, we can use the same ParticleSysConfig as in Particle system 1 63 | const byte numParticles2 = 25; 64 | 65 | Particle_Std particles2[numParticles2]; 66 | Particle_Fixed source2; 67 | Emitter_Fountain emitter2(0,0,5, &source2); 68 | ParticleSys pSys2(&g, numParticles2, particles2, &emitter2); 69 | 70 | // we only need one renderer. 71 | FastLEDRenderer renderer(&g); 72 | 73 | 74 | void setup() { 75 | FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); 76 | FastLED.setBrightness( BRIGHTNESS ); 77 | 78 | randomSeed(analogRead(0)); 79 | 80 | renderer.reset(leds); 81 | 82 | Particle_Std::ay = -1; // this affects all particles. 83 | 84 | pSys.perCycle = 10; // particles emitted every cycle 85 | emitter.minLife = 20; 86 | emitter.maxLife = 80; 87 | source.x = g.center_x+(g.res_x/2); // center and 1/2 pixel to the right 88 | source.y = g.max_y-(g.res_y/2); // lowest pixel 89 | 90 | 91 | pSys2.perCycle = 7; // particles emitted every cycle 92 | emitter2.minLife = 20; 93 | emitter2.maxLife = 70; 94 | source2.x = g.center_x-(g.res_x/2); // center and 1/2 pixel to the left 95 | source2.y = g.max_y-(g.res_y/2)-(g.res_y*3); // lowest pixel and three pixels up 96 | } 97 | 98 | void loop() { 99 | pSys.update(); 100 | pSys2.update(); 101 | renderer.reset(leds); 102 | renderer.render(&g, particles, numParticles, leds); // render first particle system 103 | renderer.render(&g, particles2, numParticles2, leds); // render second particle system 104 | FastLED.show(); 105 | delay(30); 106 | } 107 | 108 | -------------------------------------------------------------------------------- /examples/PainterFastLED/PainterFastLED.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * An example for the Arduino particle system library 12 | * Creates a spinning particle painter 13 | */ 14 | 15 | #include 16 | 17 | #define LED_WIDTH 8 18 | #define LED_HEIGHT 8 19 | 20 | // set ledSerpentineLayout to true if your matrix looks wrong ;) - see Example "XYMatrix" in FastLED library. 21 | const bool ledSerpentineLayout = false; 22 | // translates from x, y into an index into the LED array 23 | uint16_t XY( uint8_t x, uint8_t y) { 24 | if(y >= LED_HEIGHT) { y = LED_HEIGHT - 1; } 25 | if(x >= LED_WIDTH) { x = LED_WIDTH - 1; } 26 | uint16_t ret; 27 | if(ledSerpentineLayout == false) { 28 | ret = (y * LED_WIDTH) + x; 29 | } else { 30 | if( y & 0x01) { 31 | // Odd rows run backwards 32 | uint8_t revX = (LED_WIDTH - 1) - x; 33 | ret = (y * LED_WIDTH) + revX; 34 | } else { 35 | // Even rows run forwards 36 | ret = (y * LED_WIDTH) + x; 37 | } 38 | } 39 | return ret; 40 | } 41 | 42 | // Particle System 43 | 44 | #include 45 | 46 | #define NUM_LEDS (LED_WIDTH * LED_HEIGHT) 47 | #define LED_PIN 7 48 | #define COLOR_ORDER GRB 49 | #define CHIPSET WS2811 50 | #define BRIGHTNESS 32 51 | CRGB leds[ NUM_LEDS ]; 52 | 53 | const byte numParticles = 35; 54 | 55 | ParticleSysConfig g(LED_WIDTH, LED_HEIGHT); 56 | Particle_Fixed particles[numParticles]; 57 | Particle_Attractor source(g.center_x, g.center_y); 58 | Emitter_Fountain emitter(0, 5, 2, &source); 59 | ParticleSys pSys(&g, numParticles, particles, &emitter); 60 | FastLEDRenderer renderer(&g); 61 | 62 | void setup() { 63 | FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); 64 | FastLED.setBrightness( BRIGHTNESS ); 65 | 66 | randomSeed(analogRead(0)); 67 | 68 | renderer.reset(leds); 69 | 70 | source.vx = 3; 71 | source.vy = 1; 72 | source.x = 10; 73 | source.y = 10; 74 | emitter.minLife = 150; 75 | emitter.maxLife = 150; 76 | 77 | } 78 | 79 | void loop() { 80 | pSys.update(); 81 | renderer.reset(leds); 82 | renderer.render(&g, particles, numParticles, leds); 83 | FastLED.show(); 84 | delay(30); 85 | } 86 | 87 | -------------------------------------------------------------------------------- /examples/SmokerFastLED/SmokerFastLED.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * An example for the Arduino particle system library 12 | * Creates a colored smoke effect 13 | */ 14 | 15 | #include 16 | 17 | #define LED_WIDTH 8 18 | #define LED_HEIGHT 8 19 | 20 | // set ledSerpentineLayout to true if your matrix looks wrong ;) - see Example "XYMatrix" in FastLED library. 21 | const bool ledSerpentineLayout = false; 22 | // translates from x, y into an index into the LED array 23 | uint16_t XY( uint8_t x, uint8_t y) { 24 | if(y >= LED_HEIGHT) { y = LED_HEIGHT - 1; } 25 | if(x >= LED_WIDTH) { x = LED_WIDTH - 1; } 26 | uint16_t ret; 27 | if(ledSerpentineLayout == false) { 28 | ret = (y * LED_WIDTH) + x; 29 | } else { 30 | if( y & 0x01) { 31 | // Odd rows run backwards 32 | uint8_t revX = (LED_WIDTH - 1) - x; 33 | ret = (y * LED_WIDTH) + revX; 34 | } else { 35 | // Even rows run forwards 36 | ret = (y * LED_WIDTH) + x; 37 | } 38 | } 39 | return ret; 40 | } 41 | 42 | // Particle System 43 | 44 | #include 45 | 46 | #define NUM_LEDS (LED_WIDTH * LED_HEIGHT) 47 | #define LED_PIN 7 48 | #define COLOR_ORDER GRB 49 | #define CHIPSET WS2811 50 | #define BRIGHTNESS 32 51 | CRGB leds[ NUM_LEDS ]; 52 | 53 | const byte numParticles = 25; 54 | 55 | ParticleSysConfig g(LED_WIDTH, LED_HEIGHT); 56 | Particle_Std particles[numParticles]; 57 | Particle_Attractor source(g.center_x, g.center_y); 58 | Emitter_Fountain emitter(0, 0, 5, &source); 59 | ParticleSys pSys(&g, numParticles, particles, &emitter); 60 | FastLEDRenderer renderer(&g); 61 | 62 | void setup() { 63 | FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); 64 | FastLED.setBrightness( BRIGHTNESS ); 65 | 66 | randomSeed(analogRead(0)); 67 | 68 | renderer.reset(leds); 69 | 70 | source.vx = 3; 71 | source.vy = 1; 72 | source.x = random(50)+100; 73 | source.y = random(10)+1; 74 | source.atf = 2; 75 | emitter.minLife = 100; 76 | emitter.maxLife = 200; 77 | pSys.perCycle = 2; 78 | 79 | } 80 | 81 | void loop() { 82 | pSys.update(); 83 | renderer.reset(leds); 84 | renderer.render(&g, particles, numParticles, leds); 85 | FastLED.show(); 86 | delay(30); 87 | } 88 | 89 | -------------------------------------------------------------------------------- /examples/SpinFastLED/SpinFastLED.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * An example for the Arduino particle system library 12 | * Creates a spinning galaxy effect 13 | */ 14 | 15 | #include 16 | 17 | #define LED_WIDTH 8 18 | #define LED_HEIGHT 8 19 | 20 | // set ledSerpentineLayout to true if your matrix looks wrong ;) - see Example "XYMatrix" in FastLED library. 21 | const bool ledSerpentineLayout = false; 22 | // translates from x, y into an index into the LED array 23 | uint16_t XY( uint8_t x, uint8_t y) { 24 | if(y >= LED_HEIGHT) { y = LED_HEIGHT - 1; } 25 | if(x >= LED_WIDTH) { x = LED_WIDTH - 1; } 26 | uint16_t ret; 27 | if(ledSerpentineLayout == false) { 28 | ret = (y * LED_WIDTH) + x; 29 | } else { 30 | if( y & 0x01) { 31 | // Odd rows run backwards 32 | uint8_t revX = (LED_WIDTH - 1) - x; 33 | ret = (y * LED_WIDTH) + revX; 34 | } else { 35 | // Even rows run forwards 36 | ret = (y * LED_WIDTH) + x; 37 | } 38 | } 39 | return ret; 40 | } 41 | 42 | // Particle System 43 | 44 | #include 45 | 46 | #define NUM_LEDS (LED_WIDTH * LED_HEIGHT) 47 | #define LED_PIN 7 48 | #define COLOR_ORDER GRB 49 | #define CHIPSET WS2811 50 | #define BRIGHTNESS 32 51 | CRGB leds[ NUM_LEDS ]; 52 | 53 | const byte numParticles = 30; 54 | 55 | ParticleSysConfig g(LED_WIDTH, LED_HEIGHT); 56 | Particle_Std particles[numParticles]; 57 | Emitter_Spin emitter(&g, 5, 3); 58 | ParticleSys pSys(&g, numParticles, particles, &emitter); 59 | FastLEDRenderer renderer(&g); 60 | 61 | void setup() { 62 | FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); 63 | FastLED.setBrightness( BRIGHTNESS ); 64 | 65 | randomSeed(analogRead(0)); 66 | 67 | renderer.reset(leds); 68 | 69 | emitter.oscilate = true; 70 | } 71 | 72 | void loop() { 73 | pSys.update(); 74 | renderer.fade(leds); 75 | renderer.render(&g, particles, numParticles, leds); 76 | FastLED.show(); 77 | delay(30); 78 | } 79 | 80 | -------------------------------------------------------------------------------- /examples/StarfieldFastLED/StarfieldFastLED.ino: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Gilad Dayagi. All rights reserved. 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU Lesser General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | */ 9 | 10 | /* 11 | * An example for the Arduino particle system library 12 | * Creates a starfield effect 13 | */ 14 | 15 | #include 16 | 17 | #define LED_WIDTH 8 18 | #define LED_HEIGHT 8 19 | 20 | // set ledSerpentineLayout to true if your matrix looks wrong ;) - see Example "XYMatrix" in FastLED library. 21 | const bool ledSerpentineLayout = false; 22 | // translates from x, y into an index into the LED array 23 | uint16_t XY( uint8_t x, uint8_t y) { 24 | if(y >= LED_HEIGHT) { y = LED_HEIGHT - 1; } 25 | if(x >= LED_WIDTH) { x = LED_WIDTH - 1; } 26 | uint16_t ret; 27 | if(ledSerpentineLayout == false) { 28 | ret = (y * LED_WIDTH) + x; 29 | } else { 30 | if( y & 0x01) { 31 | // Odd rows run backwards 32 | uint8_t revX = (LED_WIDTH - 1) - x; 33 | ret = (y * LED_WIDTH) + revX; 34 | } else { 35 | // Even rows run forwards 36 | ret = (y * LED_WIDTH) + x; 37 | } 38 | } 39 | return ret; 40 | } 41 | 42 | // Particle System 43 | 44 | #include 45 | 46 | #define NUM_LEDS (LED_WIDTH * LED_HEIGHT) 47 | #define LED_PIN 7 48 | #define COLOR_ORDER GRB 49 | #define CHIPSET WS2811 50 | #define BRIGHTNESS 32 51 | CRGB leds[ NUM_LEDS ]; 52 | 53 | const byte numParticles = 30; 54 | 55 | ParticleSysConfig g(LED_WIDTH, LED_HEIGHT); 56 | Particle_Std particles[numParticles]; 57 | Particle_Fixed source(g.center_x, g.center_y); 58 | Emitter_Fountain emitter(8, &source); 59 | ParticleSys pSys(&g, numParticles, particles, &emitter); 60 | FastLEDRenderer renderer(&g); 61 | 62 | void setup() { 63 | FastLED.addLeds(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); 64 | FastLED.setBrightness( BRIGHTNESS ); 65 | 66 | randomSeed(analogRead(0)); 67 | 68 | renderer.reset(leds); 69 | } 70 | 71 | void loop() { 72 | pSys.update(); 73 | renderer.fade(leds); 74 | renderer.render(&g, particles, numParticles, leds); 75 | FastLED.show(); 76 | delay(25); 77 | } 78 | 79 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | About 2 | ----- 3 | A particle system library for arduino for arbitrary matrix sizes 4 | Based on code by Gilad Dayagi ( https://github.com/giladaya/arduino-particle-sys ) 5 | Mainly intended to be used with low-resolution displays (like an 8x8 RGB matrix). 6 | 7 | Installation 8 | ------------ 9 | Clone the repo into the arduino libraries directory 10 | 11 | Dependencies 12 | ------------ 13 | The FastLEDRenderer.cpp and .h depend on the FastLED library ( http://fastled.io ) 14 | 15 | RAM Usage 16 | --------- 17 | This version of the Particle System can be used for an arbitrary size of matrix (up to 256x256 Pixels) 18 | The particle coordinates and other values use 16-bit integers to hold the relevant values. 19 | If you have a LED Matrix of 8x8 Pixels or smaller on hardware with limited RAM (i.E. atmega328 with 2kb of RAM), I recommend to use the original Particle System: https://github.com/giladaya/arduino-particle-sys 20 | 21 | 22 | Hardware 23 | -------- 24 | Any Arduino compatible hardware, but due to RAM usage I recommend something beefy, like a teensy ( http://pjrc.com/teensy/ ) 25 | 26 | Examples 27 | -------- 28 | The following examples are included in the library: 29 | 30 | - FlameFastLED: https://youtu.be/pmHItuRvXjg 31 | - GreenFireFastLED: https://youtu.be/ukAbi08XwAk 32 | - MultiFlameFastLED: https://youtu.be/iJiRIr-yuUg 33 | - PainterFastLED: https://youtu.be/3tO_BpcsZSA 34 | - SmokerFastLED: https://youtu.be/Hw3fQnBcnMI 35 | - SpinFastLED: https://youtu.be/XBxegSs1yZs 36 | 37 | Notes 38 | ----- 39 | If you are working with a narrow LED Matrix (for example 8 x 32 pixels), the Particle_Attractor tends to suck the source right in his center. 40 | This can be corrected using one of several ways: 41 | 42 | 1. use a higher res_y in the ParticleSysConfig class (in the above example use res_x = 32 (default) and res_y = 128 (4 x default)). The particle system then is calculated as a square, but painted in a squished form. 43 | 2. lower the attractor force of the Particle_Attractor (atf - property, the default value is 4) 44 | 3. change the attractor force constantly in the loop, for example: ( source.atf = map(beatsin8(50),0,255,-2,3); // this varies the attractor force between -2 (pushing away) and 3 (attracting) 50 times per minute - see FastLED library for the use of the beatsin8 function...) 45 | 46 | I used the first approach in the right side of this video: https://youtu.be/osnOcP0NfYc 47 | --------------------------------------------------------------------------------