Unravel Engine C++ Reference
Loading...
Searching...
No Matches
particle_emitter_component.cpp
Go to the documentation of this file.
3#include "math/transform.hpp"
5#include <logging/logging.h>
7
8
9namespace math
10{
11template<>
12auto gradient_lerp(const frange_t& start, const frange_t& end, float progress) -> frange_t
13{
14 return frange_t(gradient_lerp(start.min, end.min, progress), gradient_lerp(start.max, end.max, progress));
15}
16}
17
18
19namespace unravel
20{
21
22void particle_emitter_component::on_create_component(entt::registry& r, entt::entity e)
23{
24 entt::handle entity(r, e);
25 auto& component = entity.get<particle_emitter_component>();
26 component.set_owner(entity);
27
28 // Initialize uniforms with default values
29 component.uniforms_.reset();
30 // Create the particle emitter
31 component.recreate_emitter();
32}
33
34void particle_emitter_component::on_destroy_component(entt::registry& r, entt::entity e)
35{
36 entt::handle entity(r, e);
38 {
39 auto& component = entity.get<particle_emitter_component>();
40
41 // Destroy the emitter if it exists
42 if(isValid(component.emitter_handle_))
43 {
44 psDestroyEmitter(component.emitter_handle_);
45 component.emitter_handle_.idx = UINT16_MAX;
46 }
47 }
48}
49
51{
52 enabled_ = enabled;
53}
54
56{
57 return enabled_;
58}
59
61{
62 return emitter_handle_;
63}
64
66{
67 if(shape_ != shape)
68 {
69 shape_ = shape;
71 }
72}
73
75{
76 return shape_;
77}
78
80{
81 if(direction_ != direction)
82 {
83 direction_ = direction;
85 }
86}
87
89{
90 return direction_;
91}
92
94{
95 if(max_particles_ != max_particles)
96 {
97 max_particles_ = max_particles;
99 }
100}
101
103{
104 return max_particles_;
105}
106
107
108void particle_emitter_component::set_emission_lifetime(std::chrono::duration<float> lifetime)
109{
110 uniforms_.m_emissionLifetime = lifetime.count();
111}
112
113auto particle_emitter_component::get_emission_lifetime() const -> std::chrono::duration<float>
114{
115 return std::chrono::duration<float>(uniforms_.m_emissionLifetime);
116}
117
122
124{
125 return uniforms_.m_gravityScale;
126}
127
129{
130 uniforms_.m_particlesPerSecond = math::max(emission_rate, 0.0f);
131
133}
134
136{
137 return uniforms_.m_particlesPerSecond;
138}
139
141{
142 uniforms_.m_temporalMotion = math::clamp(temporal_motion, 0.0f, 1.0f);
143}
144
146{
147 return uniforms_.m_temporalMotion;
148}
149
151{
152 uniforms_.m_velocityDamping = math::clamp(velocity_damping, 0.0f, 1.0f);
153}
154
156{
157 return uniforms_.m_velocityDamping;
158}
159
164
166{
167 return uniforms_.m_forceOverLifetime;
168}
169
174
176{
177 return uniforms_.m_emissionShapeScale;
178}
179
181{
182 uniforms_.m_sizeBySpeedRange = size_range;
183}
184
186{
187 return uniforms_.m_sizeBySpeedRange;
188}
189
191{
192 uniforms_.m_sizeBySpeedVelocityRange = velocity_range;
193}
194
199
201{
202 uniforms_.m_colorBySpeedGradient = gradient;
203 uniforms_.m_colorBySpeedGradient.generate_lut(256); // Generate LUT for optimization
204}
205
207{
208 return uniforms_.m_colorBySpeedGradient;
209}
210
212{
213 uniforms_.m_colorBySpeedVelocityRange = velocity_range;
214}
215
220
222{
223 uniforms_.m_lifetimeByEmitterSpeedGradient = gradient;
224 // uniforms_.m_lifetimeByEmitterSpeedGradient.generate_lut(256);
225}
226
228{
229 return uniforms_.m_lifetimeByEmitterSpeedGradient;
230}
231
236
241
242void particle_emitter_component::set_lifetime(std::chrono::duration<float> lifetime)
243{
244 uniforms_.m_lifetime = math::max(lifetime.count(), 0.0f);
246}
247
248auto particle_emitter_component::get_lifetime() const -> std::chrono::duration<float>
249{
250 return std::chrono::duration<float>(uniforms_.m_lifetime);
251}
252
254{
255 uniforms_.m_velocityGradient = gradient;
256 uniforms_.m_velocityGradient.generate_lut(256); // Generate LUT for optimization
257}
258
260{
261 return uniforms_.m_velocityGradient;
262}
263
265{
266 uniforms_.m_scaleGradient = gradient;
267 uniforms_.m_scaleGradient.generate_lut(256); // Generate LUT for optimization
268}
269
271{
272 return uniforms_.m_scaleGradient;
273}
274
276{
277 uniforms_.m_blendGradient = gradient;
278 uniforms_.m_blendGradient.generate_lut(256); // Generate LUT for optimization
279}
280
282{
283 return uniforms_.m_blendGradient;
284}
285
287{
288 uniforms_.m_blendMultiplier = math::clamp(multiplier, 0.0f, 1.0f);
289}
290
292{
293 return uniforms_.m_blendMultiplier;
294}
295
297{
298 uniforms_.m_playing = true;
299 uniforms_.m_paused = false;
300}
301
303{
304 uniforms_.m_playing = false;
305 uniforms_.m_paused = false;
306}
307
309{
310 uniforms_.m_playing = false;
311 uniforms_.m_paused = false;
312 // Reset the emitter to clear all particles
314}
315
317{
318 if(uniforms_.m_playing)
319 {
320 uniforms_.m_paused = true;
321 }
322}
323
325{
326 if(uniforms_.m_playing)
327 {
328 uniforms_.m_paused = false;
329 }
330}
331
333{
334 return uniforms_.m_playing;
335}
336
338{
339 return uniforms_.m_paused;
340}
341
343{
344 uniforms_.m_loop = loop;
345}
346
348{
349 return uniforms_.m_loop;
350}
351
353{
354 uniforms_.m_colorGradient = gradient;
355 uniforms_.m_colorGradient.generate_lut(256); // Generate LUT for optimization
356}
357
358auto particle_emitter_component::get_color_gradient() const -> const math::gradient<math::color>&
359{
360 return uniforms_.m_colorGradient;
361}
362
364{
365 uniforms_.m_easePos = easing;
366}
367
369{
370 return uniforms_.m_easePos;
371}
372
373// Blend and scale easing removed - interpolation is now handled by gradients
374
376{
377 return psGetNumParticles(emitter_handle_);
378}
379
381{
382 math::bbox bounds(math::vec3(-1.0f), math::vec3(1.0f));
383 psGetAabb(emitter_handle_, bounds);
384 return bounds;
385}
386
388{
389 auto bounds = get_world_bounds();
390 if(!psHasUpdated(emitter_handle_))
391 {
392 bounds.mul(world_transform);
393 }
394 return bounds;
395}
396
398{
399 texture_ = texture;
400}
401
403{
404 if(texture_.is_valid())
405 {
406 return texture_;
407 }
409}
410
411
413{
414 if(isValid(emitter_handle_) && enabled_)
415 {
416 // Store the world transform directly (unified approach for both simulation methods)
417 // This is much more efficient than decomposing and recomposing
418 uniforms_.m_prevTransform = uniforms_.m_transform;
419 uniforms_.m_transform = world_transform;
420
421 auto tex = [&]()
422 {
423 if(texture_.is_valid())
424 {
425 return texture_.get();
426 }
427 return material::default_color_map().get();
428 }();
429 uniforms_.m_texture = tex->native_handle();
430
431 psUpdateEmitter(emitter_handle_, dt.count(), &uniforms_);
432 }
433}
434
435
437{
438 return uniforms_;
439}
440
442{
443 // Destroy existing emitter
444 if(isValid(emitter_handle_))
445 {
446 psDestroyEmitter(emitter_handle_);
447 emitter_handle_.idx = UINT16_MAX;
448 }
449
450 // Create new emitter
451 emitter_handle_ = psCreateEmitter(shape_, direction_, max_particles_);
452
453 if(!isValid(emitter_handle_))
454 {
455 APPLOG_ERROR("Failed to create particle emitter");
456 return;
457 }
458
459}
460
462{
463 if(isValid(emitter_handle_))
464 {
465 psResetEmitter(emitter_handle_);
466 }
467}
468
474
476{
477 return uniforms_.m_simulationSpace;
478}
479
480
481} // namespace unravel
void generate_lut(size_t lut_size=256)
Definition gradient.hpp:222
General purpose transformation class designed to maintain each component of the transformation separa...
Definition transform.hpp:27
static auto default_color_map() -> asset_handle< gfx::texture > &
Gets the default color map.
Definition material.cpp:15
void set_owner(entt::handle owner)
Sets the owner of the component.
Component that wraps particle system emitter functionality.
auto get_texture() const -> const asset_handle< gfx::texture > &
auto get_size_by_speed_range() const -> const frange_t &
void set_blend_gradient(const math::gradient< frange_t > &gradient)
void set_size_by_speed_range(const frange_t &size_range)
void set_color_by_speed_velocity_range(const frange_t &velocity_range)
void set_shape(EmitterShape::Enum shape)
Sets the emitter shape.
auto get_color_by_speed_velocity_range() const -> const frange_t &
void set_texture(const asset_handle< gfx::texture > &texture)
auto get_uniforms() const -> const EmitterUniforms &
Gets the emitter uniforms for direct access.
static void on_destroy_component(entt::registry &r, entt::entity e)
Called when the component is destroyed.
auto get_simulation_space() const -> SimulationSpace::Enum
void recreate_emitter()
Recreates the emitter with current shape and direction.
void set_lifetime(std::chrono::duration< float > lifetime)
auto get_max_particles() const -> uint32_t
Gets the maximum number of particles.
void update_emitter(const math::transform &world_transform, delta_t dt)
Updates the emitter with external transform data.
void set_color_by_speed_gradient(const math::gradient< math::color > &gradient)
auto get_lifetime_by_emitter_speed_gradient() const -> const math::gradient< float > &
void set_size_by_speed_velocity_range(const frange_t &velocity_range)
void set_enabled(bool enabled)
Sets whether the emitter is enabled.
void set_direction(EmitterDirection::Enum direction)
Sets the emitter direction.
void set_simulation_space(SimulationSpace::Enum space)
auto get_emitter_handle() const -> EmitterHandle
Gets the emitter handle.
void reset_emitter()
Resets the emitter, clearing all particles and resetting internal state.
void set_position_easing(bx::Easing::Enum easing)
auto get_scale_gradient() const -> const math::gradient< frange_t > &
void set_velocity_gradient(const math::gradient< frange_t > &gradient)
void set_force_over_lifetime(const math::vec3 &force)
void set_emission_shape_scale(const math::vec3 &scale)
auto get_shape() const -> EmitterShape::Enum
Gets the emitter shape.
void set_color_gradient(const math::gradient< math::color > &gradient)
auto is_enabled() const -> bool
Checks if the emitter is enabled.
auto get_direction() const -> EmitterDirection::Enum
Gets the emitter direction.
auto get_color_by_speed_gradient() const -> const math::gradient< math::color > &
auto get_velocity_gradient() const -> const math::gradient< frange_t > &
auto get_lifetime() const -> std::chrono::duration< float >
auto get_updated_world_bounds(const math::transform &world_transform) const -> math::bbox
void set_lifetime_by_emitter_speed_gradient(const math::gradient< float > &gradient)
void set_emission_lifetime(std::chrono::duration< float > lifetime)
auto get_color_gradient() const -> const math::gradient< math::color > &
auto get_blend_gradient() const -> const math::gradient< frange_t > &
auto get_size_by_speed_velocity_range() const -> const frange_t &
static void on_create_component(entt::registry &r, entt::entity e)
Called when the component is created.
auto get_emission_lifetime() const -> std::chrono::duration< float >
void set_lifetime_by_emitter_speed_range(const frange_t &speed_range)
void set_scale_gradient(const math::gradient< frange_t > &gradient)
auto get_position_easing() const -> bx::Easing::Enum
auto get_lifetime_by_emitter_speed_range() const -> const frange_t &
void set_max_particles(uint32_t max_particles)
Sets the maximum number of particles.
std::chrono::duration< float > delta_t
range< float > frange_t
float scale
Definition hub.cpp:25
#define APPLOG_ERROR(...)
Definition logging.h:20
Definition imgui.h:25
Definition bbox.cpp:5
auto gradient_lerp(const vec4 &start, const vec4 &end, float progress) -> vec4
Definition gradient.cpp:8
Hash specialization for batch_key to enable use in std::unordered_map.
void psResetEmitter(EmitterHandle _handle)
bool psHasUpdated(EmitterHandle _handle)
EmitterHandle psCreateEmitter(EmitterShape::Enum _shape, EmitterDirection::Enum _direction, uint32_t _maxParticles)
uint32_t psGetNumParticles(EmitterHandle _handle)
void psGetAabb(EmitterHandle _handle, math::bbox &_outAabb)
void psUpdateEmitter(EmitterHandle _handle, float _dt, EmitterUniforms *_uniforms)
void psDestroyEmitter(EmitterHandle _handle)
entt::entity entity
math::gradient< math::color > m_colorGradient
math::transform m_transform
frange_t m_sizeBySpeedRange
math::transform m_prevTransform
bx::Easing::Enum m_easePos
math::gradient< frange_t > m_blendGradient
bgfx::TextureHandle m_texture
frange_t m_lifetimeByEmitterSpeedRange
math::gradient< frange_t > m_scaleGradient
math::gradient< frange_t > m_velocityGradient
math::gradient< float > m_lifetimeByEmitterSpeedGradient
frange_t m_sizeBySpeedVelocityRange
SimulationSpace::Enum m_simulationSpace
math::gradient< math::color > m_colorBySpeedGradient
math::vec3 m_forceOverLifetime
math::vec3 m_emissionShapeScale
frange_t m_colorBySpeedVelocityRange
Represents a handle to an asset, providing access and management functions.
auto is_valid() const -> bool
Checks if the handle is valid.
auto get(bool wait=true) const -> std::shared_ptr< T >
Gets the shared pointer to the asset.
Storage for box vector values and wraps up common functionality.
Definition bbox.h:21
bool isValid(SpriteHandle _handle)
Definition debugdraw.h:34