Lamp-Da 0.1
A compact lantern project
Loading...
Searching...
No Matches
particle_system.hpp
Go to the documentation of this file.
1
5#ifndef PARTICLE_SYSTEM_H
6#define PARTICLE_SYSTEM_H
7
8#include <cstdint>
9#include <functional>
10
11#include "src/system/ext/random8.h"
13
15
16#include "particle.hpp"
17
18namespace lampda::modes {
19
20using LampTy = hardware::LampTy;
21
27{
28public:
29 ParticleSystem() : particuleCount(0) { reset(); }
30
34 void reset()
35 {
36 isOccupiedSpaces.reset();
37 isAllocated.reset();
38 }
39
44 void set_max_particle_count(const uint16_t _particleCount)
45 {
46 particuleCount = std::min<uint16_t>(ParticleSystem::maxParticuleCount, _particleCount);
47 reset();
48 }
49
54 void init_particules(const std::function<int16_t(size_t)>& positionGeneratorFunction)
55 {
56 isOccupiedSpaces.reset();
57 isAllocated.reset();
58 for (size_t i = 0; i < particuleCount; ++i)
59 {
60 spawn_particule(i, positionGeneratorFunction);
61 }
62 }
63
69 bool init_deferred_particules(uint8_t maxParticlesToPop,
70 const std::function<int16_t(size_t)>& positionGeneratorFunction)
71 {
72 for (size_t i = 0; i < particuleCount and maxParticlesToPop > 0; ++i)
73 {
74 if (isAllocated[i])
75 {
76 // already allocated, do not reuse
77 continue;
78 }
79 spawn_particule(i, positionGeneratorFunction);
80 maxParticlesToPop--;
81 }
82 // still some uncreated particles
83 return maxParticlesToPop > 0;
84 }
85
92 void iterate_no_collisions(const utils::vec3d& accelerationCartesian,
93 const float deltaTime_s,
94 const bool shouldContrain = true)
95 {
96 for (size_t i = 0; i < particuleCount; ++i)
97 {
98 // do not iterate non allocated particles
99 if (not isAllocated[i])
100 continue;
101
102 Particle& p = particules[i];
103 // apply force and constrain
104 p.apply_acceleration(accelerationCartesian, deltaTime_s, shouldContrain);
105 }
106 }
107
114 void iterate_with_collisions(const utils::vec3d& accelerationCartesian,
115 const float deltaTime_s,
116 const bool shouldContrain = true)
117 {
118 for (size_t i = 0; i < particuleCount; ++i)
119 {
120 // do not iterate non allocated particles
121 if (not isAllocated[i])
122 continue;
123
124 Particle& p = particules[i];
125 const int16_t ledIndex = p._savedLampIndex;
126
127 // simulate instead of updating directly
128 const Particle& newP = p.simulate_after_acceleration(accelerationCartesian, deltaTime_s, shouldContrain);
129
130 // update particle position in occupation set
131 const int16_t newLedIndex = newP._savedLampIndex;
132 if (newLedIndex != ledIndex)
133 {
134 // check collision : no collision
135 if (not is_position_taken(newLedIndex))
136 {
137 isOccupiedSpaces[ledIndex] = false;
138 isOccupiedSpaces[newLedIndex] = true;
139 }
140 // check collision : collision !!
141 else
142 {
143 // refuse movement, rebound speed
144 p.thetaSpeed_radS = -p.thetaSpeed_radS * 0.75;
145 p.zSpeed_mS = -p.zSpeed_mS * 0.75;
146 continue;
147 }
148 }
149
150 // update particle
151 p = newP;
152 }
153 }
154
161 uint16_t depop_particules(const std::function<bool(const Particle&)>& shouldDepopFunction)
162 {
163 uint16_t particleCount = 0;
164 for (size_t i = 0; i < particuleCount; ++i)
165 {
166 // do not depop non allocated particles
167 if (not isAllocated[i])
168 continue;
169
170 auto& parti = particules[i];
171 if (shouldDepopFunction(parti))
172 {
173 isAllocated[i] = false;
174 isOccupiedSpaces[parti._savedLampIndex] = false;
175 }
176 else
177 {
178 particleCount += 1;
179 }
180 }
181 return particleCount;
182 }
183
189 uint16_t show(const std::function<uint32_t(int16_t, const Particle&)> sample_color, LampTy& lamp)
190 {
191 uint16_t particleCount = 0;
192 for (size_t i = 0; i < particuleCount; ++i)
193 {
194 // do not show non allocated particles
195 if (not isAllocated[i])
196 continue;
197 const auto& particle = particules[i];
198 const auto& index = particle._savedLampIndex;
199 if (modes::is_led_index_valid(index))
200 lamp.setPixelColor(index, sample_color(i, particle));
201 else
202 particleCount += 1;
203 }
204 return particleCount;
205 }
206
208 uint16_t get_number_of_active() const
209 {
210 uint16_t particleCount = 0;
211 for (size_t i = 0; i < particuleCount; ++i)
212 {
213 // do not show non allocated particles
214 if (not isAllocated[i])
215 continue;
216 particleCount += 1;
217 }
218 return particleCount;
219 }
220
221protected:
223 bool is_position_taken(const int16_t pos) const { return isOccupiedSpaces[pos]; }
224
230 void spawn_particule(const size_t index, const std::function<int16_t(size_t)>& positionGeneratorFunction)
231 {
232 int16_t pos = positionGeneratorFunction(index);
233 int maxTries = 3;
234 while (ParticleSystem::is_position_taken(pos) and maxTries > 0)
235 {
236 pos = positionGeneratorFunction(index);
237 maxTries--;
238 }
239 // generate start position from user function
240 const auto& helixCoordinates = modes::strip_to_helix_unconstraint(pos);
241 particules[index] = Particle(utils::vec3d {helixCoordinates.x, helixCoordinates.y, helixCoordinates.z});
242 isAllocated[index] = true;
243 isOccupiedSpaces[pos] = true;
244 }
245
246private:
247 static constexpr uint16_t maxParticuleCount = 512;
248 Particle particules[maxParticuleCount];
250 common::BitSet<LED_COUNT> isOccupiedSpaces;
251
253 uint16_t particuleCount;
254};
255
256} // namespace lampda::modes
257
258#endif
Define a compact bitset class for compile-time sized bit arrays.
A compact, zero-allocation bitset for compile-time sized bit arrays.
Definition: bitset.h:23
void reset() noexcept
Set all bits to 0.
Definition: bitset.h:74
Define a particle system ALL PARTICLE SYSTEM SHARE THE SAME PÄRTICLE SUBSET.
Definition: particle_system.hpp:27
void spawn_particule(const size_t index, const std::function< int16_t(size_t)> &positionGeneratorFunction)
Spawn a particle.
Definition: particle_system.hpp:230
uint16_t get_number_of_active() const
Return the number of active particles.
Definition: particle_system.hpp:208
bool init_deferred_particules(uint8_t maxParticlesToPop, const std::function< int16_t(size_t)> &positionGeneratorFunction)
Init the particles from a initialization function, in a timed defered way.
Definition: particle_system.hpp:69
uint16_t show(const std::function< uint32_t(int16_t, const Particle &)> sample_color, LampTy &lamp)
Display this particle system.
Definition: particle_system.hpp:189
bool is_position_taken(const int16_t pos) const
Return True if the position is already occupied.
Definition: particle_system.hpp:223
void iterate_no_collisions(const utils::vec3d &accelerationCartesian, const float deltaTime_s, const bool shouldContrain=true)
Advance the particle simulation, ignoring collisions.
Definition: particle_system.hpp:92
void set_max_particle_count(const uint16_t _particleCount)
Call when you want to change the particle count of the simulation Can be called once when starting th...
Definition: particle_system.hpp:44
uint16_t depop_particules(const std::function< bool(const Particle &)> &shouldDepopFunction)
Filter particles depending on condition.
Definition: particle_system.hpp:161
void init_particules(const std::function< int16_t(size_t)> &positionGeneratorFunction)
Init the particles from a initialization function.
Definition: particle_system.hpp:54
void reset()
reset system to zero count
Definition: particle_system.hpp:34
void iterate_with_collisions(const utils::vec3d &accelerationCartesian, const float deltaTime_s, const bool shouldContrain=true)
Advance the particle simulation, taking collisions in account.
Definition: particle_system.hpp:114
Define the main led strip interaction object.
Contains basic interface types to implement custom user modes.
Definition: control_fixed_modes.hpp:12
hardware::LampTy LampTy
Define a particle in cylindrical space, and movement equations on the cylinder surface.
Definition: particle.hpp:22
static constexpr bool is_led_index_valid(const int16_t ledIndex)
True if the given strip index is a valid one.
Definition: lamp_type.hpp:1193
static constexpr HelixXYZTy strip_to_helix_unconstraint(const int16_t n)
convert strip index to 3D coordinates, without checks on led index. This allows to use 3D coordinates...
Definition: lamp_type.hpp:1182
Define a single particle for a particle system.
Define a particle in 3D space. it has a position and speed.
Definition: particle.hpp:37
void apply_acceleration(const utils::vec3d &accelerationCartesian_m, const float deltaTime_s, const bool shouldContrain=true)
apply a cartesian acceleration to this particulate
Definition: particle.hpp:94
int16_t _savedLampIndex
optimization
Definition: particle.hpp:207
Particle simulate_after_acceleration(const utils::vec3d &accelerationCartesian_m, const float deltaTime_s, const bool shouldContrain=true) const
Simulate this particle movement as a new particle.
Definition: particle.hpp:136
float thetaSpeed_radS
angular speed, in radian/seconds
Definition: particle.hpp:200
float zSpeed_mS
linear speed, in meter/seconds
Definition: particle.hpp:201
Main interface between the user and the hardware of the lamp.
Definition: lamp_type.hpp:118
void LMBD_INLINE setPixelColor(uint16_t n, uint32_t color)
(indexable) Set the n-th LED color
Definition: lamp_type.hpp:878
float x
x coordinate in 2D
Definition: vector_math.h:16
3d vector in any space
Definition: vector_math.h:54