FastLED 3.9.15
Loading...
Searching...
No Matches
wave_simulation.h
Go to the documentation of this file.
1/*
2This is the WaveSimulation API. These classes allow flexible super sampling
3to achieve much better visual quality. They will also run the simulator
4update multiple times in order to achieve consistent speed between super
5sampling factors.
6
7A super sampling value of 2x will give the best results for the CPU consumption
8as most artifacts will be averaged out at this resolution.
9
10Based on works and code by Shawn Silverman.
11*/
12
13#pragma once
14
15#include "fl/math/math.h" // for fl::min, fl::max
17
18#include "fl/math/grid.h"
19#include "fl/stl/unique_ptr.h" // For unique_ptr
20#include "fl/math/supersample.h"
21#include "fl/stl/int.h"
22#include "fl/stl/noexcept.h"
23
24namespace fl {
25
27
28// -----------------------------------------------------------------------------
29// New supersampled 1D simulation class.
30//
31// This class mimics the supersampling logic of WaveSimulation2D.
32// The constructor accepts the desired downsampled length and a supersampling
33// multiplier (via a SuperSample enum). Internally, it creates a high-resolution
34// simulation of size (multiplier * length), and its accessor methods average
35// over or replicate across the corresponding block of high-res cells.
37 public:
38 // Constructor:
39 // - length: desired downsampled grid length.
40 // - factor: supersampling multiplier (e.g., 1x, 2x, 4x, or 8x).
41 // Higher values yield better quality but are more cpu intensive.
42 // - speed and dampening are passed on to the internal simulation.
45 float speed = 0.16f, int dampening = 6);
46
47 void init(u32 length, SuperSample factor, float speed, int dampening);
48
50 if (u32(factor) == mMultiplier) {
51 return;
52 }
53 init(mOuterLength, factor, mSim->getSpeed(), mSim->getDampenening());
54 }
55
56 // Only applies to getu8().
57 void setEasingMode(U8EasingFunction mode) { mU8Mode = mode; }
58
60
61 // Delegate methods to the internal simulation.
62 void setSpeed(float speed);
63 void setDampening(int damp);
64 int getDampenening() const;
65 float getSpeed() const;
66
67 // Runs the simulator faster by updating it multiple times.
68 void setExtraFrames(u8 extra);
69
70 // Downsampled getter for the floating point value at index x.
71 // It averages over the corresponding 'multiplier'-sized block in the
72 // high-res simulation.
73 float getf(fl::size x) const;
74
75 // Downsampled getter for the Q15 (fixed point) value at index x.
76 // It averages the multiplier cells of Q15 values.
77 i16 geti16(fl::size x) const;
78 i16 geti16Previous(fl::size x) const;
79
80 bool geti16All(fl::size x, i16 *curr, i16 *prev, i16 *diff) const;
81
82 // Downsampled getters for the 8-bit representations.
83 i8 geti8(fl::size x) const;
84
85 u8 getu8(fl::size x) const;
86
87 // Check if x is within the bounds of the outer (downsampled) simulation.
88 bool has(fl::size x) const;
89
90 // Upsampling setter: set the value at an outer grid cell x by replicating
91 // it to the corresponding multiplier cells in the high-res simulation.
92 void setf(fl::size x, float value);
93
94 void setHalfDuplex(bool on) { mSim->setHalfDuplex(on); }
95
96 // Advance the simulation one time step.
97 void update();
98
99 // Get the outer (downsampled) grid length.
100 u32 getLength() const;
101
103
104 private:
105 u32 mOuterLength; // Length of the downsampled simulation.
107 u32 mMultiplier; // Supersampling multiplier (e.g., 2, 4, or 8).
109 // Internal high-resolution simulation.
111};
112
114 public:
115 // Constructor:
116 // - W and H specify the desired inner grid size of the downsampled
117 // simulation.
118 // - 'factor' selects the supersampling mMultiplier (e.g., 2x, 4x, or 8x).
119 // Higher values yield better quality but are more cpu intensive.
120 // - Internally, the simulation is created with dimensions (factor*W x
121 // factor*H).
122 // - 'speed' and 'dampening' parameters are passed on to the internal
123 // simulation.
124 WaveSimulation2D(u32 W, u32 H,
126 float speed = 0.16f, float dampening = 6.0f);
127
128 void init(u32 width, u32 height, SuperSample factor, float speed,
129 int dampening);
130
132
133 // Delegated simulation methods.
134 void setSpeed(float speed);
135
136 void setExtraFrames(u8 extra);
137
138 void setDampening(int damp);
139
141
142 int getDampenening() const;
143
144 float getSpeed() const;
145
147 if (u32(factor) == mMultiplier) {
148 return;
149 }
150 // Preserve a user-set stencil across re-init. Without this, the
151 // wrapper's auto-select (NinePointIsotropic at multiplier >= 2)
152 // overwrites a toggle the user made via setStencil().
153 const LaplacianStencil saved_stencil = mSim->getStencil();
154 const bool stencil_was_user_set = mUserSetStencil;
155 init(mOuterWidth, mOuterHeight, factor, mSim->getSpeed(),
156 mSim->getDampenening());
157 if (stencil_was_user_set) {
158 mSim->setStencil(saved_stencil);
159 mUserSetStencil = true;
160 }
161 }
162
163 // Override the auto-selected Laplacian stencil. Calling this marks the
164 // choice as "user set" so subsequent setSuperSample() calls preserve
165 // it instead of re-applying the multiplier-based default. The default
166 // (no setStencil() ever called) is auto-selection: NinePointIsotropic
167 // at SuperSample >= 2X, FivePoint at 1X. See WaveSimulation2D_Real::
168 // setStencil() for the stencil semantics.
170 mSim->setStencil(s);
171 mUserSetStencil = true;
172 }
173 LaplacianStencil getStencil() const FL_NOEXCEPT { return mSim->getStencil(); }
174
175 void setXCylindrical(bool on) { mSim->setXCylindrical(on); }
176
177 // Downsampled getter for the floating point value at (x,y) in the outer
178 // grid. It averages over the corresponding multiplier×multiplier block in
179 // the high-res simulation.
180 float getf(fl::size x, fl::size y) const;
181
182 // Downsampled getter for the Q15 (fixed point) value at (x,y).
183 // It averages the multiplier×multiplier block of Q15 values.
184 i16 geti16(fl::size x, fl::size y) const;
185 i16 geti16Previous(fl::size x, fl::size y) const;
186
187 bool geti16All(fl::size x, fl::size y, i16 *curr, i16 *prev,
188 i16 *diff) const;
189
190 // Downsampled getters for the 8-bit representations.
191 i8 geti8(fl::size x, fl::size y) const;
192
193 // Special function to get the value as a u8 for drawing / gradients.
194 // Ease out functions are applied to this when in half duplex mode.
195 u8 getu8(fl::size x, fl::size y) const;
196
197 // Check if (x,y) is within the bounds of the outer (downsampled) grid.
198 bool has(fl::size x, fl::size y) const;
199
200 // Upsampling setter: set the value at an outer grid cell (x,y) by
201 // replicating it to all cells of the corresponding multiplier×multiplier
202 // block in the high-res simulation.
203 void setf(fl::size x, fl::size y, float value);
204
205 void seti16(fl::size x, fl::size y, i16 value);
206
207 void setHalfDuplex(bool on) { mSim->setHalfDuplex(on); }
208
209 // Advance the simulation one time step.
210 void update();
211
212 // Get the outer grid dimensions.
213 u32 getWidth() const;
214 u32 getHeight() const;
215
216 // Configure whether to use the change grid tracking optimization
217 void setUseChangeGrid(bool enabled);
218 bool getUseChangeGrid() const { return mUseChangeGrid; }
219
221
222 private:
223 u32 mOuterWidth; // Width of the downsampled (outer) grid.
224 u32 mOuterHeight; // Height of the downsampled (outer) grid.
226 u32 mMultiplier = 1; // Supersampling multiplier (e.g., 1, 2, 4, or 8).
228 bool mUseChangeGrid = false; // Whether to use change grid tracking (default: disabled for better visuals)
229 // True once setStencil() has been called from outside. Used to keep
230 // the user's stencil choice sticky across setSuperSample() re-inits.
231 bool mUserSetStencil = false;
232 // Internal high-resolution simulation.
234 fl::Grid<i16> mChangeGrid; // Needed for multiple updates.
235};
236
237} // namespace fl
uint16_t speed
Definition Noise.ino:66
static const int H
Definition PerfDisc.ino:20
static const int W
Definition PerfDisc.ino:19
WaveSimulation1D_Real & real()
float getf(fl::size x) const
~WaveSimulation1D() FL_NOEXCEPT=default
fl::unique_ptr< WaveSimulation1D_Real > mSim
void setEasingMode(U8EasingFunction mode)
i16 geti16Previous(fl::size x) const
U8EasingFunction mU8Mode
void setSuperSample(SuperSample factor)
bool geti16All(fl::size x, i16 *curr, i16 *prev, i16 *diff) const
u8 getu8(fl::size x) const
void init(u32 length, SuperSample factor, float speed, int dampening)
WaveSimulation1D(u32 length, SuperSample factor=SuperSample::SUPER_SAMPLE_NONE, float speed=0.16f, int dampening=6)
i8 geti8(fl::size x) const
void setHalfDuplex(bool on)
void setf(fl::size x, float value)
bool has(fl::size x) const
i16 geti16(fl::size x) const
void setSuperSample(SuperSample factor)
i8 geti8(fl::size x, fl::size y) const
WaveSimulation2D(u32 W, u32 H, SuperSample factor=SuperSample::SUPER_SAMPLE_NONE, float speed=0.16f, float dampening=6.0f)
void seti16(fl::size x, fl::size y, i16 value)
void setStencil(LaplacianStencil s) FL_NOEXCEPT
i16 geti16(fl::size x, fl::size y) const
fl::Grid< i16 > mChangeGrid
LaplacianStencil getStencil() const FL_NOEXCEPT
void setXCylindrical(bool on)
float getf(fl::size x, fl::size y) const
bool getUseChangeGrid() const
i16 geti16Previous(fl::size x, fl::size y) const
WaveSimulation2D_Real & real()
void setEasingMode(U8EasingFunction mode)
bool geti16All(fl::size x, fl::size y, i16 *curr, i16 *prev, i16 *diff) const
~WaveSimulation2D() FL_NOEXCEPT=default
void setf(fl::size x, fl::size y, float value)
bool has(fl::size x, fl::size y) const
U8EasingFunction mU8Mode
u8 getu8(fl::size x, fl::size y) const
void init(u32 width, u32 height, SuperSample factor, float speed, int dampening)
fl::unique_ptr< WaveSimulation2D_Real > mSim
void setUseChangeGrid(bool enabled)
void setHalfDuplex(bool on)
fl::UISlider length("Length", 1.0f, 0.0f, 1.0f, 0.01f)
fl::UISlider dampening("Dampening", 6.0f, 0.0f, 10.0f, 0.1f)
unsigned char u8
Definition stdint.h:131
constexpr int type_rank< T >::value
u8 u8 height
Definition blur.h:186
U8EasingFunction
u8 width
Definition blur.h:186
signed char i8
Definition stdint.h:130
SuperSample
Definition supersample.h:4
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT