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

Adding Particle System with many new FX #4506

Open
wants to merge 251 commits into
base: main
Choose a base branch
from

Conversation

DedeHai
Copy link
Collaborator

@DedeHai DedeHai commented Jan 19, 2025

this replaces the previous PR (#3823) since I made too many changes and a rebase was needed.
Some info on the particle system:

  • effects look best at 40-80FPS
  • all FX can be overlaid: overlay is auto-detected, blurring may not work properly in multi-overlay
  • PS and its buffers reside in segment data and is dynamically managed to keep a small RAM memory footprint (local render buffers are shared between segments)
  • since most FX are random number based, segments do not run in sync
  • 1M and 2M ESP8266 have the particle effects disabled for memory reasons

there are three compile time defines

  • WLED_DISABLE_PARTICLESYSTEM2D -> disables 2D system and FX, automatically set if WLED_DISABLE_2D is set
  • WLED_DISABLE_PARTICLESYSTEM1D -> disables 1D system and FX
  • WLED_PS_DONT_REPLACE_FX -> re-enables the replaced FX (uses 12k more flash)

Replaced FX
to save on flash, effects that have a particle system based replacement are disabled. This saves 12k of flash. Users who want the originals back can custom compile using compile flag.

  • Ghost Rider -> PS Ghost Rider (with new options and faster rendering)
  • Blobs -> PS Blobs (with new options, optional AR functionality and nicer rendering)
  • Fire 2012 -> PS Fire (1D and 2D versions)
  • Fireworks 1D -> PS Fireworks (1D and 2D versions)
  • Dancing Shadows -> PS Dancing Shadows
  • Fireworks Starburst -> PS Starburst
  • Glitter & Solid Glitter -> PS Sparkler (with overlay and settings tweked to users liking)
  • Sparkle -> PS Sparkler
  • Rolling Balls -> PS Pinball with checkmark "rolling"
  • Multi Comet -> PS Pinball with gravity set to 0

Known issues:

  • ESP8266 truncates the FX info JSON, the last added FX have missing sliders
  • changing segment arrangements or changing FX during transitions can somettimes lead to crashes due memory race conditions/pointer issues
  • replaced FX are not 100% identical

Summary by CodeRabbit

  • New Features
    • Expanded LED animations with a suite of new particle effects for more diverse and dynamic visual displays.
    • Introduced configurable options to enable or disable specific particle effects on select setups, giving users greater control over performance and appearance.
    • Enhanced transition handling for smoother visual updates during effect changes.

not yet final version but working
update from another commit that got lost
this somehow also got lost from an earlier commit
particle box now is more random in random mode (still a work in progress)
firework is now more configurable by sliders
particle attractor animation does not work, somthing wrong with pointer allocation, it worked with static variables
still unknown, why more than 256 particles are needed in memory allocation to not make it crash, but it works for now
at the expense of more ram usage, animations now have more options for color control (already used in fireworks now)
improved efficiency for stackup (pushback), added code to correctly determine direction if particles meed (probably overkill but now its there)
untested, need to verify it works
…ables to 32bit for faster calculation

32bit variables are faster on ESP32, so use them whenever a variable is used a lot, it saves one instruction per access.
it made very little difference in performance, but for ESP8266 it may matter so it is set permanently there. graphically the difference is also very small (sometimes a particle gets brighter or less saturated)
particle pile-up did not work correctly, now fixed
@DedeHai
Copy link
Collaborator Author

DedeHai commented Jan 23, 2025

tested combinations that work with ESP8266 without touching JSON buffer size: the only thing that does not work is enabling both 1D and 2D particle system, which is now prohibited by an #ifdef. Enabling the replaced FX still produces a working UI.

@DedeHai
Copy link
Collaborator Author

DedeHai commented Jan 23, 2025

@netmindz regarding

it does feel a bit wasteful of effect IDs to leave the old ones unused in our default builds.

the way I understand the addEffect() function in FX.cpp it will already fill up the reserved slots with additional FX, given that they call the function with id=255 (which all usermods currently do)

@DedeHai
Copy link
Collaborator Author

DedeHai commented Jan 26, 2025

Updated to play nice with blending styles. @blazoncek regarding

I specifically do not approve changing blending mode during effect run.

that (intermediate) disabling is necessary to not have one FX fade out and the other fade in as that is not how PS transitions work anymore when "fade" style is set. It is also only disabled during the buffer transfer. I don't see a better way except if another blending style specifically for the PS is added, but that is just confusing. If you have any other good ideas, I am open to suggestions.

@blazoncek
Copy link
Collaborator

If you have any other good ideas

I do not know if it is a "good idea" but am just thinking out loud:
Forget about blending inside PS system. There should be no notion of two separate runs of PS effects to know of each other (although you think it looks really good but it does so in edge cases only). Leave blending (mixing) to strip logic (as mentioned above) or segment logic (inside setPixelColor()).
It may sound counterproductive or counterintuitive but consider this scenario: 32x32 matrix with 5 segments set up, 0,0-16,16; 16,0-32,16; 0,16-16,32; 16,16-32,32 and 0,0-32,32 (or even a more complex one). Each of them running separate effect, the last segment overlays all others. It will be a lot of work for PS system to correctly blend that.

If done outside of PS it is as simple* as color_blend() for each pixel.
* not really that simple but simpler still

@DedeHai
Copy link
Collaborator Author

DedeHai commented Jan 26, 2025

thanks for the input. I agree it would be better to do blending in one place BUT: blending between FX inside the PS is only done for one segment, not multiple. The reason it does that is to share the buffer AND the particles for one segment: if you had your proposed scenario, each segment would require two render buffers and twice the particles, which would exceed RAM already at 32x32 and multiple segments + transitions. Disabling the "particle blending" is as easy as changing two or three if's as it already disables it when not using 'fade' style. The "two PS FX can interact" part is more of an addition than a necessity, it could be a user selectable option as well.
edit:
I would like to get some user's feedback on the PS as well as the 'blending' and adjust if requested.

@DedeHai
Copy link
Collaborator Author

DedeHai commented Jan 27, 2025

@netmindz feel free to squash-merge this

…, 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
Member

netmindz commented Feb 1, 2025

@netmindz feel free to squash-merge this

Sorry I wasn't sure what you meant by this and got distracted before I replied. Was this just a note to use squash when I merge, but not yet or a request for merge with squash now?

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 1, 2025

Just a suggestion to squash merge so commits are compacted. Merge when you took a look at it, any remaining issues are minor and can be worked out with more feedback from users

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 3, 2025

@netmindz regarding the max number of FX: I think increasing mode (and _modeT) to int16_t and making the "reserved" to be -1 instead of the current 255 should be possible without too much fuss. I can take a stab at it in a new PR.

@blazoncek
Copy link
Collaborator

blazoncek commented Feb 3, 2025

@DedeHai there are numerous old effects that can be removed (and replaced with other existing effects with added sliders and options) some of which you already modified or consolidated. I would recommend to do that.

These are: 11, 14, 19, 52, 53, 60, 77, 93, 94, 99, 102, 103, 117

@blazoncek
Copy link
Collaborator

I think increasing mode (and _modeT) to int16_t ... should be possible without too much fuss.

Are you aware of all consequences? I guess not otherwise you wouldn't make such a bold claim.

@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 3, 2025

Are you aware of all consequences? I guess not otherwise you wouldn't make such a bold claim.

I am not. please do enlighten me: which is the tricky part?

@blazoncek
Copy link
Collaborator

Sync etc.

if a PS FX is partially overlapping, it will render in overlay mode
@DedeHai
Copy link
Collaborator Author

DedeHai commented Feb 10, 2025

@coderabbitai review

Copy link

coderabbitai bot commented Feb 10, 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 bot commented Feb 10, 2025

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

💤 Files selected but had no reviewable changes (1)
  • wled00/FX.cpp

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

Walkthrough

The changes update the build configuration and particle effects support. The platformio.ini file now includes new build flags to disable particle systems in various environments. The FX module has been enhanced by replacing the previous MODE_COUNT definition with a new particle mode and adding multiple new particle effect macros. A new method (loadOldPalette) was added to the Segment class, and a new header file introduces ParticleSystem2D and ParticleSystem1D classes with associated update, emission, and allocation methods. Additionally, a minor formatting adjustment was made in the configuration file.

Changes

File(s) Change Summary
platformio.ini Added build flags -D WLED_DISABLE_PARTICLESYSTEM2D and -D WLED_DISABLE_PARTICLESYSTEM1D for multiple environments (NodeMCU, ESP8266, ESP01 variants).
wled00/FX.h, wled00/FX_fcn.cpp, wled00/FXparticleSystem.h Expanded particle system support: replaced MODE_COUNT with FX_MODE_PARTICLEVOLCANO and introduced new FX_MODE_* macros; added loadOldPalette() method in Segment; introduced ParticleSystem2D/1D classes with update, emitter, and allocation methods.
wled00/cfg.cpp Added a newline at the end of the file in the serializeConfigSec function for formatting consistency.

Sequence Diagram(s)

sequenceDiagram
    participant Core as WLED Core
    participant Seg as Segment
    participant PS as Particle System
    Core->>Seg: Trigger animation update
    Seg->>Seg: Check transition state
    alt Transition Active
        Seg->>Seg: Call loadOldPalette() → loadPalette()
    end
    Seg->>PS: Update particle effects
    PS->>PS: Process update (emit particles, apply forces, update state)
Loading

🪧 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.

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: 0

🧹 Nitpick comments (9)
wled00/FXparticleSystem.h (4)

1-9: Consider renaming the file header.
The file name and initial comment mention "FXparticleSystem.cpp," but the actual file appears to be a header (".h"). Ensuring consistency between file name, top-level comment, and included references will help avoid confusion.


33-44: Evaluate bitfield usage for booleans.
In the 'partMem' struct, multiple booleans are used (e.g., finalTransfer, transferParticles), but only some entries are grouped into bitfields (watchdog is an 8-bit integer). Converting more booleans into bitfields or combining them could reduce memory footprints, which is crucial on ESP8266.


158-163: Consider a destructor or explicit memory freeing.
The ParticleSystem2D constructor sets up external memory pointers (particles, sources, etc.). Although this is typically managed externally, ensure there's no scenario where the system is allocated but never freed.


210-220: Reduce the size of collision logic for performance.
Methods like handleCollisions() could be large, especially if the device must handle many particles. Consider partitioning collisions into spatial buckets or using more efficient data structures if performance degrades with high particle counts.

wled00/FX.h (3)

325-353: Document newly introduced particle effect modes.
These macros (FX_MODE_PARTICLEVOLCANO to FX_MODE_PS1DSONICSTREAM) add numerous effect modes. In future maintenance, ensure they are well-documented in user-facing material (UI labels, docs) so that users understand their distinctive behaviors.


510-510: Clarify the padding purpose.
This inline comment merely notes a padding byte in the Transition struct. Consider expanding the comment to indicate why it is necessary (alignment vs. future usage) so future maintainers do not remove it inadvertently.


606-607: Rename getmodeBlend() for consistency.
The static function getmodeBlend() returns a boolean. For clarity, consider renaming it to isModeBlend(), better reflecting its true/false return.

-inline static bool     getmodeBlend(void)              { return _modeBlend; }
+inline static bool     isModeBlend(void)               { return _modeBlend; }
wled00/FX_fcn.cpp (2)

14-14: Consider moving memory service definition to FX.h as suggested by TODO comment.

The TODO comment indicates that memory service functionality should be defined in FX.h. This would improve code organization by keeping related functionality together.


474-478: Add null pointer check in loadOldPalette.

While the implementation is clean and focused, consider adding a null pointer check before accessing _t to prevent potential crashes.

void Segment::loadOldPalette(void) {
-  if(isInTransition())
+  if(isInTransition() && _t != nullptr)
    loadPalette(_currentPalette, _t->_palTid);
}
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b64cd36 and bb0de15.

📒 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
🔇 Additional comments (8)
wled00/FXparticleSystem.h (5)

56-58: Validate speed limiting range.
The limitSpeed() function clamps speed between ±PS_P_MAXSPEED (120). Verify that 120 is an acceptable limit for all hardware targets and does not break any intended behaviors for advanced or large displays.


94-102: Review struct alignment and potential padding in PSparticle.
This struct is 10 bytes. Depending on compiler alignment rules, it might insert padding if used in arrays or forced alignment. Carefully confirm how the memory manager and transitions handle partial alignment to avoid subtle bugs.


135-140: Review advanced particle size logic.
The PSsizeControl struct introduces multiple bitfields and flags (e.g., grow, shrink, pulsate). Verify all size manipulations are tested thoroughly, especially edge cases with maxsize or 0.


200-205: Confirm that advanced pointers gather correct offsets.
PSadvancedParticle and PSsizeControl pointers are marked nullable. Validate that code paths where they are null do not lead to accidental dereferencing.


249-253: Validate memory constraints for large 2D arrays.
allocateParticleSystemMemory2D can allocate up to thousands of particles for large segments. For lower-memory devices (1M/2M ESP8266), this might cause out-of-memory errors. Confirm compile-time guards or runtime checks are sufficient.

wled00/FX.h (1)

655-655: Ensure backward compatibility in loadOldPalette().
This new method loads an “old FX palette” into the current palette. Verify it correctly handles older configurations or user data to prevent color mismatches, especially during transitions.

wled00/FX_fcn.cpp (1)

1556-1558: LGTM! Good use of conditional compilation.

The particle system memory handling is properly guarded by conditional compilation, allowing it to be disabled when not needed.

platformio.ini (1)

370-370: LGTM! Appropriate handling of memory constraints.

The build flags to disable particle systems are correctly applied to memory-constrained environments, particularly ESP8266 boards. This aligns well with the PR objectives to manage memory usage.

Also applies to: 380-380, 388-388, 397-398, 407-408, 415-416, 426-427, 436-437, 445-446

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants