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 <stdint.h>
16
17#include "fl/math_macros.h" // if needed for MAX/MIN macros
18#include "fl/namespace.h"
19#include "fl/scoped_ptr.h"
20#include "fl/warn.h"
22
23#include "fl/grid.h"
24#include "fl/ptr.h"
25#include "fl/supersample.h"
26#include "fl/xymap.h"
27#include "fx/fx.h"
28#include "fx/fx2d.h"
29
30namespace fl {
31
33
34// -----------------------------------------------------------------------------
35// New supersampled 1D simulation class.
36//
37// This class mimics the supersampling logic of WaveSimulation2D.
38// The constructor accepts the desired downsampled length and a supersampling
39// multiplier (via a SuperSample enum). Internally, it creates a high-resolution
40// simulation of size (multiplier * length), and its accessor methods average
41// over or replicate across the corresponding block of high-res cells.
43 public:
44 // Constructor:
45 // - length: desired downsampled grid length.
46 // - factor: supersampling multiplier (e.g., 1x, 2x, 4x, or 8x).
47 // Higher values yield better quality but are more cpu intensive.
48 // - speed and dampening are passed on to the internal simulation.
49 WaveSimulation1D(uint32_t length,
51 float speed = 0.16f, int dampening = 6);
52
53 void init(uint32_t length, SuperSample factor, float speed, int dampening);
54
56 if (uint32_t(factor) == mMultiplier) {
57 return;
58 }
59 init(mOuterLength, factor, mSim->getSpeed(), mSim->getDampenening());
60 }
61
62 // Only applies to getu8().
63 void setEasingMode(U8EasingFunction mode) { mU8Mode = mode; }
64
65 ~WaveSimulation1D() = default;
66
67 // Delegate methods to the internal simulation.
68 void setSpeed(float speed);
69 void setDampening(int damp);
70 int getDampenening() const;
71 float getSpeed() const;
72
73 // Runs the simulator faster by updating it multiple times.
74 void setExtraFrames(uint8_t extra);
75
76 // Downsampled getter for the floating point value at index x.
77 // It averages over the corresponding 'multiplier'-sized block in the
78 // high-res simulation.
79 float getf(size_t x) const;
80
81 // Downsampled getter for the Q15 (fixed point) value at index x.
82 // It averages the multiplier cells of Q15 values.
83 int16_t geti16(size_t x) const;
84 int16_t geti16Previous(size_t x) const;
85
86 bool geti16All(size_t x, int16_t *curr, int16_t *prev, int16_t *diff) const;
87
88 // Downsampled getters for the 8-bit representations.
89 int8_t geti8(size_t x) const;
90
91 uint8_t getu8(size_t x) const;
92
93 // Check if x is within the bounds of the outer (downsampled) simulation.
94 bool has(size_t x) const;
95
96 // Upsampling setter: set the value at an outer grid cell x by replicating
97 // it to the corresponding multiplier cells in the high-res simulation.
98 void setf(size_t x, float value);
99
100 void setHalfDuplex(bool on) { mSim->setHalfDuplex(on); }
101
102 // Advance the simulation one time step.
103 void update();
104
105 // Get the outer (downsampled) grid length.
106 uint32_t getLength() const;
107
109
110 private:
111 uint32_t mOuterLength; // Length of the downsampled simulation.
112 uint8_t mExtraFrames = 0;
113 uint32_t mMultiplier; // Supersampling multiplier (e.g., 2, 4, or 8).
115 // Internal high-resolution simulation.
117};
118
120 public:
121 // Constructor:
122 // - W and H specify the desired inner grid size of the downsampled
123 // simulation.
124 // - 'factor' selects the supersampling mMultiplier (e.g., 2x, 4x, or 8x).
125 // Higher values yield better quality but are more cpu intensive.
126 // - Internally, the simulation is created with dimensions (factor*W x
127 // factor*H).
128 // - 'speed' and 'dampening' parameters are passed on to the internal
129 // simulation.
130 WaveSimulation2D(uint32_t W, uint32_t H,
132 float speed = 0.16f, float dampening = 6.0f);
133
134 void init(uint32_t width, uint32_t height, SuperSample factor, float speed,
135 int dampening);
136
137 ~WaveSimulation2D() = default;
138
139 // Delegated simulation methods.
140 void setSpeed(float speed);
141
142 void setExtraFrames(uint8_t extra);
143
144 void setDampening(int damp);
145
147
148 int getDampenening() const;
149
150 float getSpeed() const;
151
153 if (uint32_t(factor) == mMultiplier) {
154 return;
155 }
156 init(mOuterWidth, mOuterHeight, factor, mSim->getSpeed(),
157 mSim->getDampenening());
158 }
159
160 void setXCylindrical(bool on) { mSim->setXCylindrical(on); }
161
162 // Downsampled getter for the floating point value at (x,y) in the outer
163 // grid. It averages over the corresponding multiplier×multiplier block in
164 // the high-res simulation.
165 float getf(size_t x, size_t y) const;
166
167 // Downsampled getter for the Q15 (fixed point) value at (x,y).
168 // It averages the multiplier×multiplier block of Q15 values.
169 int16_t geti16(size_t x, size_t y) const;
170 int16_t geti16Previous(size_t x, size_t y) const;
171
172 bool geti16All(size_t x, size_t y, int16_t *curr, int16_t *prev,
173 int16_t *diff) const;
174
175 // Downsampled getters for the 8-bit representations.
176 int8_t geti8(size_t x, size_t y) const;
177
178 // Special function to get the value as a uint8_t for drawing / gradients.
179 // Ease out functions are applied to this when in half duplex mode.
180 uint8_t getu8(size_t x, size_t y) const;
181
182 // Check if (x,y) is within the bounds of the outer (downsampled) grid.
183 bool has(size_t x, size_t y) const;
184
185 // Upsampling setter: set the value at an outer grid cell (x,y) by
186 // replicating it to all cells of the corresponding multiplier×multiplier
187 // block in the high-res simulation.
188 void setf(size_t x, size_t y, float value);
189
190 void seti16(size_t x, size_t y, int16_t value);
191
192 void setHalfDuplex(bool on) { mSim->setHalfDuplex(on); }
193
194 // Advance the simulation one time step.
195 void update();
196
197 // Get the outer grid dimensions.
198 uint32_t getWidth() const;
199 uint32_t getHeight() const;
200
202
203 private:
204 uint32_t mOuterWidth; // Width of the downsampled (outer) grid.
205 uint32_t mOuterHeight; // Height of the downsampled (outer) grid.
206 uint8_t mExtraFrames = 0;
207 uint32_t mMultiplier = 1; // Supersampling multiplier (e.g., 1, 2, 4, or 8).
209 // Internal high-resolution simulation.
211 fl::Grid<int16_t> mChangeGrid; // Needed for multiple updates.
212};
213
214} // namespace fl
uint32_t x[NUM_LAYERS]
Definition Fire2023.ino:82
uint32_t y[NUM_LAYERS]
Definition Fire2023.ino:83
UISlider dampening("Dampening", 6.0f, 0.0f, 10.0f, 0.1f)
Definition grid.h:9
void setf(size_t x, float value)
WaveSimulation1D_Real & real()
fl::scoped_ptr< WaveSimulation1D_Real > mSim
void init(uint32_t length, SuperSample factor, float speed, int dampening)
void setEasingMode(U8EasingFunction mode)
WaveSimulation1D(uint32_t length, SuperSample factor=SuperSample::SUPER_SAMPLE_NONE, float speed=0.16f, int dampening=6)
int8_t geti8(size_t x) const
int16_t geti16(size_t x) const
bool has(size_t x) const
float getf(size_t x) const
~WaveSimulation1D()=default
void setSpeed(float speed)
U8EasingFunction mU8Mode
void setDampening(int damp)
void setSuperSample(SuperSample factor)
void setExtraFrames(uint8_t extra)
uint8_t getu8(size_t x) const
int16_t geti16Previous(size_t x) const
bool geti16All(size_t x, int16_t *curr, int16_t *prev, int16_t *diff) const
uint32_t getLength() const
void setHalfDuplex(bool on)
void setSuperSample(SuperSample factor)
int16_t geti16(size_t x, size_t y) const
uint32_t getWidth() const
void init(uint32_t width, uint32_t height, SuperSample factor, float speed, int dampening)
void setExtraFrames(uint8_t extra)
uint32_t getHeight() const
void setXCylindrical(bool on)
int8_t geti8(size_t x, size_t y) const
fl::Grid< int16_t > mChangeGrid
fl::scoped_ptr< WaveSimulation2D_Real > mSim
void setSpeed(float speed)
WaveSimulation2D_Real & real()
void setEasingMode(U8EasingFunction mode)
bool geti16All(size_t x, size_t y, int16_t *curr, int16_t *prev, int16_t *diff) const
float getf(size_t x, size_t y) const
uint8_t getu8(size_t x, size_t y) const
void seti16(size_t x, size_t y, int16_t value)
void setf(size_t x, size_t y, float value)
U8EasingFunction mU8Mode
bool has(size_t x, size_t y) const
void setDampening(int damp)
~WaveSimulation2D()=default
WaveSimulation2D(uint32_t W, uint32_t H, SuperSample factor=SuperSample::SUPER_SAMPLE_NONE, float speed=0.16f, float dampening=6.0f)
int16_t geti16Previous(size_t x, size_t y) const
void setHalfDuplex(bool on)
UISlider length("Length", 1.0f, 0.0f, 1.0f, 0.01f)
uint16_t speed
Definition funky.cpp:82
Implements the FastLED namespace macros.
U8EasingFunction
@ WAVE_U8_MODE_LINEAR
@ WAVE_U8_MODE_SQRT
SuperSample
Definition supersample.h:4
@ SUPER_SAMPLE_NONE
Definition supersample.h:5
Implements a simple red square effect for 2D LED grids.
Definition crgb.h:16