Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fxparticle system pr #5

Closed
wants to merge 278 commits into from
Closed

Conversation

netmindz
Copy link
Owner

@netmindz netmindz commented Jan 26, 2025

Summary by CodeRabbit

  • New Features

    • Added multiple new particle effect modes for LED strips
    • Introduced advanced particle system for 1D and 2D environments
    • Expanded visual effects library with new particle-based modes
  • Improvements

    • Enhanced memory management for particle systems
    • Added configuration options to disable particle systems for specific environments
  • Technical Updates

    • Introduced new methods for palette and effect management
    • Added support for more complex LED lighting effects

DedeHai and others added 30 commits February 17, 2024 14:23
touch is implemented differently on S2 and S3, these changes make touch buttons work on S2 and S3
now better fits the default threshold value of 32
-removed wrap_update function, now integrated into move_update
-added more 'out of bounds' checking in fire functions, may speed it up a little
-removed particle box 'rocking boat' (buggy) and replaced with random sloshing.
-removed comments
-changed some variables into 32bit for speed boost on ESP32
-added link to KB at the top of FX.cpp
removed / added comments
-animation works but sliders are too sensitive. need to adjust the ranges
- changed firework exhaust to low saturation
- updated rotating particle spray animation
-added particle reductions for ESP8266 for all FX
-Removed collisions from Particle Perlin Noise FX, slows things down and does not contribute to a better effect experience
-lots of optimizations for ESP8266, all FX now work (at least on 160MHz but still slow)
-Some bugfixes
-removed unused variables to make compiler happy
-Now shorter names, 'PS' in front to filter the list
-Tuned default parameters to make them look better by default
-Bugfix in particle system (removed duplicate application of velocity)
-reduced PS fire RAM usage (less particles, less base flames, no noticeable difference)
-some variable renaming
-fixed fire burning more on the left side
-fixed crash in particle attractor
-added many improvements for ESP8266
-improved particle rendering efficiency
-efficiency improvements in general
-changed the way fire is rendered, now more than 2x faster
-re-tuned fire to new rendering, also seperately tuned it for ESP8266
-changed all random8() to random16() as it runs faster on ESPs
-some reformating
-some renaming of effect stuff
-fine tuning on falling particle effect
-improvements to collision handling (faster and better)
-added a (temporary) function for speed tests, will be removed again
DedeHai and others added 13 commits January 23, 2025 17:47
Includes update to use matching newer AsyncTCP on ESP32
Enable the new concurrent request and queue size limit features
of AsyncWebServer.  This should improve the handling of burst
traffic or many clients, and significantly reduce the likelihood
of OOM crashes due to HTTP requests.
This can be helpful for debugging web handler related issues.
Use the web server's queuing mechanism to call us back later.
No locking contention, but a much larger target
Copy link

coderabbitai bot commented Jan 26, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The pull request introduces a comprehensive particle system implementation for LED effects in the WLED project. The changes include adding new build flags to disable particle systems for specific environments, expanding the range of effect modes with numerous particle-based effects, and implementing both 1D and 2D particle system classes. The modifications enhance the visual effect capabilities by providing advanced particle rendering, movement, and interaction methods across different hardware configurations.

Changes

File Changes
platformio.ini Added build flags:
- -D WLED_DISABLE_PARTICLESYSTEM2D for multiple ESP8266 environments
- -D WLED_DISABLE_PARTICLESYSTEM1D for ESP8266 environments
wled00/FX.h - Added multiple new particle effect modes (FX_MODE_PARTICLEFIRE to FX_MODE_PSFIRE1D)
- Added loadOldPalette() method to Segment class
wled00/FX_fcn.cpp - Implemented loadOldPalette() method
- Modified WS2812FX::service() to include servicePSmem()
wled00/FXparticleSystem.h - Added ParticleSystem2D and ParticleSystem1D classes
- Implemented particle system initialization and management methods
wled00/cfg.cpp - Added a newline character at the end of the file

Sequence Diagram

sequenceDiagram
    participant PS as Particle System
    participant Seg as Segment
    participant FX as WS2812FX
    
    PS->>PS: Initialize Particle System
    PS->>Seg: Load Old Palette
    Seg-->>PS: Palette Loaded
    FX->>PS: Service Particle Memory
    PS->>PS: Update Particles
    PS->>PS: Render Particles
Loading

Poem

🐰 Particles dance, a digital delight,
Hopping through LEDs, a spectacular sight!
From fire to vortex, effects take flight,
Rabbit-coded magic, burning ever so bright!
Pixel pixels spinning with pure glee! 🎉


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@netmindz
Copy link
Owner Author

@coderabbitai review

Copy link

coderabbitai bot commented Jan 26, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (8)
wled00/FXparticleSystem.h (5)

15-22: Consider clarifying conditional compilation.

You wrap certain particle system functionality with WLED_DISABLE_PARTICLESYSTEM2D and WLED_DISABLE_PARTICLESYSTEM1D. Consider grouping these #ifdef directives in a single, self-contained block or adding documentation explaining their intended usages and interactions to prevent confusion when toggling them.


46-54: Strengthen error handling strategies.

These function prototypes—particularly particleMemoryManager, particleHandover, and servicePSmem—are critical for memory allocation and deallocation. It would be wise to document expected return values, possible error states, and the calling conventions (e.g., who is responsible for cleaning up memory) to improve maintainability.


56-59: Validate speed-limiting segments.

Your limitSpeed inline function enforces a hard-coded maximum speed (PS_P_MAXSPEED). Consider either exposing this threshold for advanced configuration (allowing the user to tune the limit) or documenting where it originates and why it’s immutable. This ensures the constant remains meaningful and maintainable.


104-117: Document particle flags usage.

PSparticleFlags includes several custom bits (custom1 through custom5). Document how these bits are intended to be used, or provide helper methods to set and clear them. Doing so helps new contributors avoid collisions in meaning or misuse of these seemingly “free” bits.


256-416: Replicate 2D improvements in 1D code.

ParticleSystem1D repeats much of the 2D logic with a narrower scope. If possible, consider extracting shared logic—like memory management, friction, force updates—into a base class or utility functions. This helps avoid duplication and simplifies maintenance when introducing future enhancements.

wled00/FX.h (1)

510-510: Handle new struct padding carefully.

Line 510 references “one byte of padding.” If you intend or need comfortable usage across compiler versions or architectures, explicitly documenting why this padding is necessary (e.g., alignment with a union or backward-compatibility concerns) can prevent accidental breakage.

wled00/FX_fcn.cpp (1)

14-14: Resolve TODO regarding dependencies.

The comment “// TODO: better define the required function (mem service) in FX.h?” indicates uncertainty about where servicePSmem() belongs. Decide if this belongs in FX.h or if FX_fcn.cpp is the right place to reduce cross-file dependencies and keep particle core logic together.

platformio.ini (1)

361-361: Memory optimization strategy looks good!

The selective disabling of particle systems based on board capabilities is well thought out:

  • More capable boards (nodemcuv2) only disable 2D particles
  • Memory-constrained boards (esp8266_2m, esp01_1m) disable both 1D and 2D particles
  • ESP32 variants retain full particle system support

Consider documenting the memory requirements that led to these decisions, such as:

  • Minimum RAM/flash needed for 1D particle system
  • Additional memory overhead for 2D particle system
  • Impact on other features when particle systems are enabled

Also applies to: 371-371, 379-379, 388-389, 398-399, 406-407, 417-418, 427-428, 436-437

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2d6ad41 and f7ca8fa.

📒 Files selected for processing (5)
  • platformio.ini (6 hunks)
  • wled00/FX.h (5 hunks)
  • wled00/FX_fcn.cpp (4 hunks)
  • wled00/FXparticleSystem.h (1 hunks)
  • wled00/cfg.cpp (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • wled00/cfg.cpp
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: wled_build / Build Enviornments (esp01_1m_full_compat)
  • GitHub Check: wled_build / Build Enviornments (esp01_1m_full_160)
🔇 Additional comments (5)
wled00/FXparticleSystem.h (2)

33-45: Ensure consistent memory lifecycle.

partMem is pivotal for tracking particle memory usage. Verify that the code systematically resets or updates fields like watchdog, inTransition, and transferParticles at the appropriate points to avoid stale flags. Also, ensure that the transitions between FX modes properly manage the states in this structure without risking data races or invalid pointers.


79-92: Avoid potential bitfield pitfalls.

PSsettings2D packs multiple booleans into a single byte. If the code evolves, ensure that reading/writing these bitfields remains consistent across compilers and architectures. In particular, watch for alignment or endianness issues if cross-platform usage is intended.

wled00/FX.h (1)

607-607: Expose usage of _modeBlend.

getmodeBlend() seems to be used internally during effect transitions. Consider clarifying in code comments how and when _modeBlend is modified. Doing so reduces confusion for maintainers and helps them understand transitions or layering logic in WLED.

wled00/FX_fcn.cpp (2)

471-476: Ensure safe transitions in loadOldPalette().

When loading the old palette during transitions, confirm that the function won't be called after the transitional data becomes invalid, potentially leading to memory corruption or unexpected fallback behaviors. Audits or additional checks can strengthen resilience.


1553-1555: Tie memory servicing to compile-time flags.

The call to servicePSmem() depends on whether both WLED_DISABLE_PARTICLESYSTEM2D and WLED_DISABLE_PARTICLESYSTEM1D are undefined. This conditional block could benefit from a brief comment explaining its presence so future developers know why it’s needed only when those particle systems are active.

Comment on lines 156 to 245
class ParticleSystem2D {
public:
ParticleSystem2D(const uint32_t width, const uint32_t height, const uint32_t numberofparticles, const uint32_t numberofsources, const bool isadvanced = false, const bool sizecontrol = false); // constructor
// note: memory is allcated in the FX function, no deconstructor needed
void update(void); //update the particles according to set options and render to the matrix
void updateFire(const uint8_t intensity, const bool renderonly); // update function for fire, if renderonly is set, particles are not updated (required to fix transitions with frameskips)
void updateSystem(void); // call at the beginning of every FX, updates pointers and dimensions
void particleMoveUpdate(PSparticle &part, PSparticleFlags &partFlags, PSsettings2D *options = NULL, PSadvancedParticle *advancedproperties = NULL); // move function
// particle emitters
int32_t sprayEmit(const PSsource &emitter);
void flameEmit(const PSsource &emitter);
int32_t angleEmit(PSsource& emitter, const uint16_t angle, const int32_t speed);
//particle physics
void applyGravity(PSparticle &part); // applies gravity to single particle (use this for sources)
[[gnu::hot]] void applyForce(PSparticle &part, const int8_t xforce, const int8_t yforce, uint8_t &counter);
[[gnu::hot]] void applyForce(const uint32_t particleindex, const int8_t xforce, const int8_t yforce); // use this for advanced property particles
void applyForce(const int8_t xforce, const int8_t yforce); // apply a force to all particles
void applyAngleForce(PSparticle &part, const int8_t force, const uint16_t angle, uint8_t &counter);
void applyAngleForce(const uint32_t particleindex, const int8_t force, const uint16_t angle); // use this for advanced property particles
void applyAngleForce(const int8_t force, const uint16_t angle); // apply angular force to all particles
void applyFriction(PSparticle &part, const int32_t coefficient); // apply friction to specific particle
void applyFriction(const int32_t coefficient); // apply friction to all used particles
void pointAttractor(const uint32_t particleindex, PSparticle &attractor, const uint8_t strength, const bool swallow);
// set options note: inlining the set function uses more flash so dont optimize
void setUsedParticles(const uint8_t percentage); // set the percentage of particles used in the system, 255=100%
inline uint32_t getAvailableParticles(void) { return availableParticles; } // available particles in the buffer, use this to check if buffer changed during FX init
void setCollisionHardness(const uint8_t hardness); // hardness for particle collisions (255 means full hard)
void setWallHardness(const uint8_t hardness); // hardness for bouncing on the wall if bounceXY is set
void setWallRoughness(const uint8_t roughness); // wall roughness randomizes wall collisions
void setMatrixSize(const uint32_t x, const uint32_t y);
void setWrapX(const bool enable);
void setWrapY(const bool enable);
void setBounceX(const bool enable);
void setBounceY(const bool enable);
void setKillOutOfBounds(const bool enable); // if enabled, particles outside of matrix instantly die
void setSaturation(const uint8_t sat); // set global color saturation
void setColorByAge(const bool enable);
void setMotionBlur(const uint8_t bluramount); // note: motion blur can only be used if 'particlesize' is set to zero
void setSmearBlur(const uint8_t bluramount); // enable 2D smeared blurring of full frame
void setParticleSize(const uint8_t size);
void setGravity(const int8_t force = 8);
void enableParticleCollisions(const bool enable, const uint8_t hardness = 255);

PSparticle *particles; // pointer to particle array
PSparticleFlags *particleFlags; // pointer to particle flags array
PSsource *sources; // pointer to sources
PSadvancedParticle *advPartProps; // pointer to advanced particle properties (can be NULL)
PSsizeControl *advPartSize; // pointer to advanced particle size control (can be NULL)
uint8_t* PSdataEnd; // points to first available byte after the PSmemory, is set in setPointers(). use this for FX custom data
int32_t maxX, maxY; // particle system size i.e. width-1 / height-1 in subpixels, Note: all "max" variables must be signed to compare to coordinates (which are signed)
int32_t maxXpixel, maxYpixel; // last physical pixel that can be drawn to (FX can read this to read segment size if required), equal to width-1 / height-1
uint32_t numSources; // number of sources
uint32_t usedParticles; // number of particles used in animation, is relative to 'numParticles'
//note: some variables are 32bit for speed and code size at the cost of ram

private:
//rendering functions
void ParticleSys_render();
[[gnu::hot]] void renderParticle(const uint32_t particleindex, const uint32_t brightness, const CRGB& color, const bool wrapX, const bool wrapY);
//paricle physics applied by system if flags are set
void applyGravity(); // applies gravity to all particles
void handleCollisions();
[[gnu::hot]] void collideParticles(PSparticle &particle1, PSparticle &particle2, const int32_t dx, const int32_t dy);
void fireParticleupdate();
//utility functions
void updatePSpointers(const bool isadvanced, const bool sizecontrol); // update the data pointers to current segment data space
bool updateSize(PSadvancedParticle *advprops, PSsizeControl *advsize); // advanced size control
void getParticleXYsize(PSadvancedParticle *advprops, PSsizeControl *advsize, uint32_t &xsize, uint32_t &ysize);
[[gnu::hot]] void bounce(int8_t &incomingspeed, int8_t &parallelspeed, int32_t &position, const uint32_t maxposition); // bounce on a wall
// note: variables that are accessed often are 32bit for speed
PSsettings2D particlesettings; // settings used when updating particles (can also used by FX to move sources), do not edit properties directly, use functions above
uint32_t numParticles; // total number of particles allocated by this system note: during transitions, less are available, use availableParticles
uint32_t availableParticles; // number of particles available for use (can be more or less than numParticles, assigned by memory manager)
uint32_t emitIndex; // index to count through particles to emit so searching for dead pixels is faster
int32_t collisionHardness;
uint32_t wallHardness;
uint32_t wallRoughness; // randomizes wall collisions
uint32_t particleHardRadius; // hard surface radius of a particle, used for collision detection (32bit for speed)
uint16_t collisionStartIdx; // particle array start index for collision detection
uint8_t fireIntesity = 0; // fire intensity, used for fire mode (flash use optimization, better than passing an argument to render function)
uint8_t fractionOfParticlesUsed; // percentage of particles used in the system (255=100%), used during transition updates
uint8_t forcecounter; // counter for globally applied forces
uint8_t gforcecounter; // counter for global gravity
int8_t gforce; // gravity strength, default is 8 (negative is allowed, positive is downwards)
// global particle properties for basic particles
uint8_t particlesize; // global particle size, 0 = 2 pixels, 255 = 10 pixels (note: this is also added to individual sized particles)
uint8_t motionBlur; // motion blur, values > 100 gives smoother animations. Note: motion blurring does not work if particlesize is > 0
uint8_t smearBlur; // 2D smeared blurring of full frame
uint8_t effectID; // ID of the effect that is using this particle system, used for transitions
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider splitting large class.

ParticleSystem2D is quite extensive, handling initialization, movement updates, rendering, collisions, and more. While the functionality is closely related, the class might be pushing the Single Responsibility Principle. Evaluate a split into smaller classes or modules (e.g., a dedicated collision handler) to improve clarity and reduce potential coupling.

Comment on lines +325 to +353
#define FX_MODE_PARTICLEVOLCANO 187
#define FX_MODE_PARTICLEFIRE 188
#define FX_MODE_PARTICLEFIREWORKS 189
#define FX_MODE_PARTICLEVORTEX 190
#define FX_MODE_PARTICLEPERLIN 191
#define FX_MODE_PARTICLEPIT 192
#define FX_MODE_PARTICLEBOX 193
#define FX_MODE_PARTICLEATTRACTOR 194
#define FX_MODE_PARTICLEIMPACT 195
#define FX_MODE_PARTICLEWATERFALL 196
#define FX_MODE_PARTICLESPRAY 197
#define FX_MODE_PARTICLESGEQ 198
#define FX_MODE_PARTICLECENTERGEQ 199
#define FX_MODE_PARTICLEGHOSTRIDER 200
#define FX_MODE_PARTICLEBLOBS 201
#define FX_MODE_PSDRIP 202
#define FX_MODE_PSPINBALL 203
#define FX_MODE_PSDANCINGSHADOWS 204
#define FX_MODE_PSFIREWORKS1D 205
#define FX_MODE_PSSPARKLER 206
#define FX_MODE_PSHOURGLASS 207
#define FX_MODE_PS1DSPRAY 208
#define FX_MODE_PSBALANCE 209
#define FX_MODE_PSCHASE 210
#define FX_MODE_PSSTARBURST 211
#define FX_MODE_PS1DGEQ 212
#define FX_MODE_PSFIRE1D 213
#define FX_MODE_PS1DSONICSTREAM 214
#define MODE_COUNT 215
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Validate large effect enumeration.

A considerable block of new particle effect modes (187 to 215) has been introduced. Verify that:

  1. The definitions don’t overlap with existing modes.
  2. Each effect has a matching handler in your FX function table.
  3. MODE_COUNT properly reflects this extended set, ensuring array bounds are respected.

netmindz and others added 11 commits January 26, 2025 15:19
Update AsyncWebServer and enable response queue
…, minor tweaks

- collisions are now also velocity based in 1D, there was a bug that prevented that from working well (wrong collision distance calculation)
- improvement and bugfix in 2D collision distance calculation
- added distance based pushing in 2D (instead of only using the dotproduct)
the combination of improved distance calculation and proper pushing make collisions a lot better in all tested FX
@netmindz
Copy link
Owner Author

netmindz commented Feb 3, 2025

Was just for testing CodeRabbit

@netmindz netmindz closed this Feb 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants