1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include "Image/BsColor.h"
7#include "Math/BsVector3.h"
8#include "Math/BsRandom.h"
9#include "Scene/BsSceneActor.h"
10#include "CoreThread/BsCoreObject.h"
11#include "Image/BsPixelData.h"
12#include "Math/BsAABox.h"
13#include "Particles/BsParticleDistribution.h"
14#include "Particles/BsParticleEvolver.h"
15#include "Particles/BsParticleEmitter.h"
16
17namespace bs
18{
19 struct EvaluatedAnimationData;
20 class SkeletonMask;
21 class ParticleSystem;
22 class ParticleEmitter;
23 class ParticleEvolver;
24 class ParticleSet;
25
26 namespace ct { class ParticleSystem; }
27
28 /** @addtogroup Implementation
29 * @{
30 */
31
32 /** @} */
33
34 /** @addtogroup Particles
35 * @{
36 */
37
38 /** Possible orientations when rendering billboard particles. */
39 enum class BS_SCRIPT_EXPORT(m:Particles) ParticleOrientation
40 {
41 /** Orient towards view (camera) plane. */
42 ViewPlane,
43
44 /** Orient towards view (camera) position. */
45 ViewPosition,
46
47 /** Orient with a user-provided axis. */
48 Plane
49 };
50
51 /** Space in which to spawn/transform particles. */
52 enum class BS_SCRIPT_EXPORT(m:Particles) ParticleSimulationSpace
53 {
54 /**
55 * Particles will always remain local to their transform parent. This means if the transform parent moves so will
56 * all the particles.
57 */
58 Local,
59
60 /**
61 * Particles will be placed in world space. This means they will spawn at the location of the transform parent,
62 * but are no longer affected by its transform after spawn (e.g. smoke rising from a moving train).
63 */
64 World
65 };
66
67 /** Determines how to sort particles before rendering. */
68 enum class BS_SCRIPT_EXPORT(m:Particles) ParticleSortMode
69 {
70 /** Do not sort the particles. */
71 None,
72
73 /** Sort by distance from the camera, furthest to nearest. */
74 Distance,
75
76 /** Sort by age, oldest to youngest. */
77 OldToYoung,
78
79 /** Sort by age, youngest to oldest. */
80 YoungToOld
81 };
82
83 /** Determines how are particles represented on the screen. */
84 enum class BS_SCRIPT_EXPORT(m:Particles) ParticleRenderMode
85 {
86 /** Particle is represented using a 2D quad. */
87 Billboard,
88
89 /** Particle is represented using a 3D mesh. */
90 Mesh
91 };
92
93 /** Controls depth buffer collisions for GPU simulated particles. */
94 struct BS_CORE_EXPORT BS_SCRIPT_EXPORT(m:Particles) ParticleDepthCollisionSettings : IReflectable
95 {
96 BS_SCRIPT_EXPORT()
97 ParticleDepthCollisionSettings() = default;
98
99 /** Determines if depth collisions are enabled. */
100 BS_SCRIPT_EXPORT()
101 bool enabled = false;
102
103 /**
104 * Determines the elasticity (bounciness) of the particle collision. Lower values make the collision less bouncy
105 * and higher values more.
106 */
107 BS_SCRIPT_EXPORT()
108 float restitution = 1.0f;
109
110 /**
111 * Determines how much velocity should a particle lose after a collision, in percent of its current velocity. In
112 * range [0, 1].
113 */
114 BS_SCRIPT_EXPORT()
115 float dampening = 0.5f;
116
117 /** Scale which to apply to particle size in order to determine the collision radius. */
118 BS_SCRIPT_EXPORT()
119 float radiusScale = 1.0f;
120
121 /************************************************************************/
122 /* RTTI */
123 /************************************************************************/
124
125 /** Enumerates all the fields in the type and executes the specified processor action for each field. */
126 template<class P>
127 void rttiEnumFields(P p);
128 public:
129 friend class ParticleDepthCollisonSettingsRTTI;
130 static RTTITypeBase* getRTTIStatic();
131 RTTITypeBase* getRTTI() const override;
132 };
133
134 /** @} */
135 /** @addtogroup Implementation
136 * @{
137 */
138
139 /** Common base for both sim and core thread variants of ParticleSystemSettings. */
140 struct ParticleSystemSettingsBase
141 {
142 /** Determines in which space are particles in. */
143 BS_SCRIPT_EXPORT()
144 ParticleSimulationSpace simulationSpace = ParticleSimulationSpace::World;
145
146 /** Determines how are particles oriented when rendering. */
147 BS_SCRIPT_EXPORT()
148 ParticleOrientation orientation = ParticleOrientation::ViewPlane;
149
150 /**
151 * Determines the time period during which the system runs, in seconds. This effects evaluation of distributions
152 * with curves using particle system time for evaluation.
153 */
154 BS_SCRIPT_EXPORT()
155 float duration = 5.0f;
156
157 /** Determines should the particle system time wrap around once it reaches its duration. */
158 BS_SCRIPT_EXPORT()
159 bool isLooping = true;
160
161 /**
162 * Determines the maximum number of particles that can ever be active in this system. This number is ignored
163 * if GPU simulation is enabled, and instead particle count is instead only limited by the size of the internal
164 * buffers (shared between all particle systems).
165 */
166 BS_SCRIPT_EXPORT()
167 UINT32 maxParticles = 2000;
168
169 /**
170 * If true the particle system will be simulated on the GPU. This allows much higher particle counts at lower
171 * performance cost. GPU simulation ignores any provided evolvers and instead uses ParticleGpuSimulationSettings
172 * to customize the GPU simulation.
173 */
174 BS_SCRIPT_EXPORT(category:Advanced,order:1)
175 bool gpuSimulation = false;
176
177
178 /** Determines how is each particle represented on the screen. */
179 BS_SCRIPT_EXPORT(order:2)
180 ParticleRenderMode renderMode = ParticleRenderMode::Billboard;
181
182 /**
183 * Determines should the particles only be allowed to orient themselves around the Y axis, or freely. Ignored if
184 * using the Plane orientation mode.
185 */
186 BS_SCRIPT_EXPORT(order:2)
187 bool orientationLockY = false;
188
189 /**
190 * Determines a normal of the plane to orient particles towards. Only used if particle orientation mode is set to
191 * ParticleOrientation::Plane.
192 */
193 BS_SCRIPT_EXPORT(order:2)
194 Vector3 orientationPlaneNormal = Vector3::UNIT_Z;
195
196 /**
197 * Determines how (and if) are particles sorted. Sorting controls in what order are particles rendered.
198 * If GPU simulation is enabled only distance based sorting is supported.
199 */
200 BS_SCRIPT_EXPORT(order:2)
201 ParticleSortMode sortMode = ParticleSortMode::None;
202
203 /**
204 * Determines should an automatic seed be used for the internal random number generator. This ensures the particle
205 * system yields different results each time it is ran.
206 */
207 BS_SCRIPT_EXPORT(order:2)
208 bool useAutomaticSeed = true;
209
210 /**
211 * Determines the seed to use for the internal random number generator. Allows you to guarantee identical behaviour
212 * between different runs. Only relevant if automatic seed is disabled.
213 */
214 BS_SCRIPT_EXPORT(order:2)
215 UINT32 manualSeed = 0;
216
217 /**
218 * Determines should the particle system bounds be automatically calculated, or should the fixed value provided
219 * be used. Bounds are used primarily for culling purposes. Note that automatic bounds are not supported when GPU
220 * simulation is enabled.
221 */
222 BS_SCRIPT_EXPORT(order:2)
223 bool useAutomaticBounds = true;
224
225 /**
226 * Custom bounds to use them @p useAutomaticBounds is disabled. The bounds are in the simulation space of the
227 * particle system.
228 */
229 BS_SCRIPT_EXPORT(order:2)
230 AABox customBounds;
231 };
232
233 /** Templated common base for both sim and core thread variants of ParticleSystemSettings. */
234 template<bool Core>
235 struct TParticleSystemSettings : ParticleSystemSettingsBase
236 {
237 using MaterialType = CoreVariantHandleType<Material, Core>;
238 using MeshType = CoreVariantHandleType<Mesh, Core>;
239
240 /** Material to render the particles with. */
241 BS_SCRIPT_EXPORT(loadOnAssign)
242 MaterialType material;
243
244 /** Mesh used for representing individual particles when using the Mesh rendering mode. */
245 BS_SCRIPT_EXPORT(loadOnAssign,order:2)
246 MeshType mesh;
247
248 /** Enumerates all the fields in the type and executes the specified processor action for each field. */
249 template<class P>
250 void rttiEnumFields(P processor);
251 };
252
253 /** Common base for both sim and core thread variants of ParticleVectorFieldSettings. */
254 struct ParticleVectorFieldSettingsBase
255 {
256 /** Intensity of the forces and velocities applied by the vector field. */
257 BS_SCRIPT_EXPORT()
258 float intensity = 1.0f;
259
260 /**
261 * Determines how closely does the particle velocity follow the vectors in the field. If set to 1 particles
262 * will be snapped to the exact velocity of the value in the field, and if set to 0 the field will not influence
263 * particle velocities directly.
264 */
265 BS_SCRIPT_EXPORT()
266 float tightness = 0.0f;
267
268 /** Scale to apply to the vector field bounds. This is multiplied with the bounds of the vector field resource. */
269 BS_SCRIPT_EXPORT()
270 Vector3 scale = Vector3::ONE;
271
272 /**
273 * Amount of to move the vector field by relative to the parent particle system. This is added to the bounds
274 * provided in the vector field resource.
275 */
276 BS_SCRIPT_EXPORT()
277 Vector3 offset = Vector3::ZERO;
278
279 /** Initial rotation of the vector field. */
280 BS_SCRIPT_EXPORT()
281 Quaternion rotation = Quaternion::IDENTITY;
282
283 /**
284 * Determines the amount to rotate the vector field every second, in degrees, around XYZ axis respectively.
285 * Evaluated over the particle system lifetime.
286 */
287 BS_SCRIPT_EXPORT()
288 Vector3Distribution rotationRate = Vector3(0.0f, 90.0f, 0.0f);
289
290 /**
291 * Determines should the field influence particles outside of the field bounds. If true the field will be tiled
292 * infinitely in the X direction.
293 */
294 BS_SCRIPT_EXPORT()
295 bool tilingX = false;
296
297 /**
298 * Determines should the field influence particles outside of the field bounds. If true the field will be tiled
299 * infinitely in the Y direction.
300 */
301 BS_SCRIPT_EXPORT()
302 bool tilingY = false;
303
304 /**
305 * Determines should the field influence particles outside of the field bounds. If true the field will be tiled
306 * infinitely in the Z direction.
307 */
308 BS_SCRIPT_EXPORT()
309 bool tilingZ = false;
310 };
311
312 /** Templated common base for both sim and core thread variants of ParticleVectorFieldSettings. */
313 template<bool Core>
314 struct TParticleVectorFieldSettings : ParticleVectorFieldSettingsBase
315 {
316 /** Vector field resource used for influencing the particles. */
317 BS_SCRIPT_EXPORT()
318 CoreVariantHandleType<VectorField, Core> vectorField;
319
320 /** Enumerates all the fields in the type and executes the specified processor action for each field. */
321 template<class P>
322 void rttiEnumFields(P processor);
323 };
324
325 /** @} */
326 /** @addtogroup Particles
327 * @{
328 */
329
330 /** Settings used for controlling a vector field in a GPU simulated particle system. */
331 struct BS_CORE_EXPORT BS_SCRIPT_EXPORT(m:Particles)
332 ParticleVectorFieldSettings : TParticleVectorFieldSettings<false>, IReflectable
333 {
334 /************************************************************************/
335 /* RTTI */
336 /************************************************************************/
337
338 public:
339 friend class ParticleVectorFieldSettingsRTTI;
340 static RTTITypeBase* getRTTIStatic();
341 RTTITypeBase* getRTTI() const override;
342 };
343
344 namespace ct
345 {
346 /** Core thread counterpart of bs::ParticleVectorFieldSettings. */
347 struct ParticleVectorFieldSettings : TParticleVectorFieldSettings<true>
348 { };
349 }
350
351 /** @} */
352 /** @addtogroup Implementation
353 * @{
354 */
355
356 template<> struct CoreThreadType<ParticleVectorFieldSettings> { typedef ct::ParticleVectorFieldSettings Type; };
357
358 /** Common base for both sim and core threat variants of ParticleGpuSimulationSettings. */
359 struct ParticleGpuSimulationSettingsBase
360 {
361 /** Determines particle color, evaluated over the particle lifetime. */
362 BS_SCRIPT_EXPORT()
363 ColorDistribution colorOverLifetime = Color::White;
364
365 /** Determines particle size, evaluated over the particle lifetime. Multiplied by the initial particle size. */
366 BS_SCRIPT_EXPORT()
367 Vector2Distribution sizeScaleOverLifetime = Vector2::ONE;
368
369 /** Constant acceleration to apply for each step of the simulation. */
370 BS_SCRIPT_EXPORT()
371 Vector3 acceleration = Vector3::ZERO;
372
373 /** Amount of resistance to apply in the direction opposite of the particle's velocity. */
374 BS_SCRIPT_EXPORT()
375 float drag = 0.0f;
376
377 /** Settings controlling particle depth buffer collisions. */
378 BS_SCRIPT_EXPORT()
379 ParticleDepthCollisionSettings depthCollision;
380 };
381
382 /** Templated common base for both sim and core threat variants of ParticleGpuSimulationSettings. */
383 template<bool Core>
384 struct TParticleGpuSimulationSettings : ParticleGpuSimulationSettingsBase
385 {
386 BS_SCRIPT_EXPORT()
387 CoreVariantType<ParticleVectorFieldSettings, Core> vectorField;
388
389 /** Enumerates all the fields in the type and executes the specified processor action for each field. */
390 template<class P>
391 void rttiEnumFields(P processor);
392 };
393
394 /** @} */
395 /** @addtogroup Particles
396 * @{
397 */
398
399 /** Generic settings used for controlling a ParticleSystem. */
400 struct BS_CORE_EXPORT BS_SCRIPT_EXPORT(m:Particles)
401 ParticleSystemSettings : TParticleSystemSettings<false>, IReflectable
402 {
403 /************************************************************************/
404 /* RTTI */
405 /************************************************************************/
406 public:
407 friend class ParticleSystemSettingsRTTI;
408 static RTTITypeBase* getRTTIStatic();
409 RTTITypeBase* getRTTI() const override;
410 };
411
412 /** Settings used for controlling particle system GPU simulation. */
413 struct BS_CORE_EXPORT BS_SCRIPT_EXPORT(m:Particles)
414 ParticleGpuSimulationSettings : TParticleGpuSimulationSettings<false>, IReflectable
415 {
416 /************************************************************************/
417 /* RTTI */
418 /************************************************************************/
419
420 public:
421 friend class ParticleGpuSimulationSettingsRTTI;
422 static RTTITypeBase* getRTTIStatic();
423 RTTITypeBase* getRTTI() const override;
424 };
425
426 /** @} */
427
428 /** @addtogroup Particles-Internal
429 * @{
430 */
431
432 namespace ct
433 {
434 class VectorField;
435
436 /** Core thread counterpart of bs::ParticleSystemSettings. */
437 struct ParticleSystemSettings : TParticleSystemSettings<true> { };
438
439 /** Core thread counterpart of bs::ParticleVectorFieldSettings. */
440 struct ParticleGpuSimulationSettings : TParticleGpuSimulationSettings<true> { };
441 }
442
443 /** @} */
444
445 /** @addtogroup Particles
446 * @{
447 */
448
449 /**
450 * Controls spawning, evolution and rendering of particles. Particles can be 2D or 3D, with a variety of rendering
451 * options. Particle system should be used for rendering objects that cannot properly be represented using static or
452 * animated meshes, like liquids, smoke or flames.
453 *
454 * The particle system requires you to specify at least one ParticleEmitter, which controls how are new particles
455 * generated. You will also want to specify one or more ParticleEvolver%s, which change particle properties over time.
456 */
457 class BS_CORE_EXPORT ParticleSystem final : public IReflectable, public CoreObject, public SceneActor, public INonCopyable
458 {
459 public:
460 ~ParticleSystem() final;
461
462 /** Determines general purpose settings that apply to the particle system. */
463 void setSettings(const ParticleSystemSettings& settings);
464
465 /** @copydoc setSettings */
466 const ParticleSystemSettings& getSettings() const { return mSettings; }
467
468 /** Determines settings that control particle GPU simulation. */
469 void setGpuSimulationSettings(const ParticleGpuSimulationSettings& settings);
470
471 /** @copydoc setGpuSimulationSettings */
472 const ParticleGpuSimulationSettings& getGpuSimulationSettings() const { return mGpuSimulationSettings; }
473
474 /**
475 * Set of objects that determine initial position, normal and other properties of newly spawned particles. Each
476 * particle system must have at least one emitter.
477 */
478 void setEmitters(const Vector<SPtr<ParticleEmitter>>& emitters);
479
480 /** @copydoc setEmitters */
481 const Vector<SPtr<ParticleEmitter>>& getEmitters() const { return mEmitters; }
482
483 /**
484 * Set of objects that determine how particle properties change during their lifetime. Evolvers only affect
485 * CPU simulated particles.
486 */
487 void setEvolvers(const Vector<SPtr<ParticleEvolver>>& evolvers);
488
489 /** @copydoc setEmitters */
490 const Vector<SPtr<ParticleEvolver>>& getEvolvers() const { return mEvolvers; }
491
492 /**
493 * Determines the layer bitfield that controls whether a system is considered visible in a specific camera.
494 * Layer must match camera layer in order for the camera to render the component.
495 */
496 void setLayer(UINT64 layer);
497
498 /** @copydoc setLayer() */
499 UINT64 getLayer() const { return mLayer; }
500
501 /** Starts the particle system. New particles will be emitted and existing particles will be evolved. */
502 void play();
503
504 /** Pauses the particle system. New particles will stop being emitted and existing particle state will be frozen. */
505 void pause();
506
507 /** Stops the particle system and resets it to initial state, clearing all particles. */
508 void stop();
509
510 /** Retrieves an implementation of the particle system usable only from the core thread. */
511 SPtr<ct::ParticleSystem> getCore() const;
512
513 /** Creates a new empty ParticleSystem object. */
514 static SPtr<ParticleSystem> create();
515
516 /**
517 * @name Internal
518 */
519
520 /**
521 * Updates the particle simulation by advancing it by @p timeDelta. New state will be updated in the internal
522 * ParticleSet.
523 */
524 void _simulate(float timeDelta, const EvaluatedAnimationData* animData);
525
526 /**
527 * Calculates the bounds of all the particles in the system. Should be called after a call to _simulate() to get
528 * up-to-date bounds. The bounds are in the simulation space of the particle system.
529 */
530 AABox _calculateBounds() const;
531
532 /**
533 * Advances the particle system time according to the current time, time delta and the provided settings.
534 *
535 * @param[in] time Current time to use as a base.
536 * @param[in] timeDelta Amount of time to advance the time by.
537 * @param[in] duration Maximum time allowed by the particle system.
538 * @param[in] loop Determines what happens when the time exceeds @p duration. If true the time will
539 * wrap around to 0 and start over, if false the time will be clamped to @p
540 * duration.
541 * @param[out] timeStep Actual time-step the simulation was advanced by. This is normally equal to
542 * @p timeDelta but might be a different value if time was clamped.
543 * @return New time value.
544 */
545 static float _advanceTime(float time, float timeDelta, float duration, bool loop, float& timeStep);
546
547 /** @} */
548 private:
549 friend class ParticleManager;
550 friend class ParticleSystemRTTI;
551 friend class ParticleEmitter;
552 friend class ct::ParticleSystem;
553
554 /** States the particle system can be in. */
555 enum class State
556 {
557 Uninitialized, Stopped, Paused, Playing
558 };
559
560 ParticleSystem();
561
562 /**
563 * Decrements particle lifetime, kills expired particles and executes evolvers that need to run before
564 * the simulation.
565 *
566 * @param[in] state State describing the current state of the simulation.
567 * @param[in] startIdx Index of the first particle to update.
568 * @param[in] count Number of particles to update, starting from @p startIdx.
569 * @param[in] spacing When false all particles will use the same time-step. If true the time-step will
570 * be divided by @p count so particles are uniformly distributed over the
571 * time-step.
572 * @param[in] spacingOffset Extra offset that controls the starting position of the first particle when
573 * calculating spacing. Should be in range [0, 1). 0 = beginning of the current
574 * time step, 1 = start of next particle.
575 */
576 void preSimulate(const ParticleSystemState& state, UINT32 startIdx, UINT32 count, bool spacing, float spacingOffset);
577
578 /**
579 * Integrates particle properties, advancing the simulation.
580 *
581 * @param[in] state State describing the current state of the simulation.
582 * @param[in] startIdx Index of the first particle to update.
583 * @param[in] count Number of particles to update, starting from @p startIdx.
584 * @param[in] spacing When false all particles will use the same time-step. If true the time-step will
585 * be divided by @p count so particles are uniformly distributed over the
586 * time-step.
587 * @param[in] spacingOffset Extra offset that controls the starting position of the first particle when
588 * calculating spacing. Should be in range [0, 1). 0 = beginning of the current
589 * time step, 1 = start of next particle.
590 */
591 void simulate(const ParticleSystemState& state, UINT32 startIdx, UINT32 count, bool spacing, float spacingOffset);
592
593 /**
594 * Executes evolvers that need to run after the simulation.
595 *
596 * @param[in] state State describing the current state of the simulation.
597 * @param[in] startIdx Index of the first particle to update.
598 * @param[in] count Number of particles to update, starting from @p startIdx.
599 * @param[in] spacing When false all particles will use the same time-step. If true the time-step will
600 * be divided by @p count so particles are uniformly distributed over the
601 * time-step.
602 * @param[in] spacingOffset Extra offset that controls the starting position of the first particle when
603 * calculating spacing. Should be in range [0, 1). 0 = beginning of the current
604 * time step, 1 = start of next particle.
605 */
606 void postSimulate(const ParticleSystemState& state, UINT32 startIdx, UINT32 count, bool spacing, float spacingOffset);
607
608 /** @copydoc CoreObject::createCore */
609 SPtr<ct::CoreObject> createCore() const override;
610
611 /** @copydoc SceneActor::_markCoreDirty */
612 void _markCoreDirty(ActorDirtyFlag flag = ActorDirtyFlag::Everything) override;
613
614 /** @copydoc CoreObject::syncToCore */
615 CoreSyncData syncToCore(FrameAlloc* allocator) override;
616
617 /** @copydoc CoreObject::getCoreDependencies */
618 void getCoreDependencies(Vector<CoreObject*>& dependencies) override;
619
620 /** Creates a new ParticleSystem instance without initializing it. */
621 static SPtr<ParticleSystem> createEmpty();
622
623 SPtr<SceneInstance> mScene;
624 ParticleSystemSettings mSettings;
625 ParticleGpuSimulationSettings mGpuSimulationSettings;
626 Vector<SPtr<ParticleEmitter>> mEmitters;
627 Vector<SPtr<ParticleEvolver>> mEvolvers;
628 UINT64 mLayer = 1;
629
630 // Internal state
631 UINT32 mId = 0;
632 State mState = State::Uninitialized;
633 float mTime = 0.0f;
634 UINT32 mSeed = 0;
635
636 Random mRandom;
637 ParticleSet* mParticleSet = nullptr;
638
639 /************************************************************************/
640 /* RTTI */
641 /************************************************************************/
642
643 public:
644 friend class ParticleSystemRTTI;
645 static RTTITypeBase* getRTTIStatic();
646 RTTITypeBase* getRTTI() const override;
647 };
648
649 /** @} */
650
651 /** @addtogroup Particles-Internal
652 * @{
653 */
654
655 namespace ct
656 {
657 /** Core thread counterpart of bs::ParticleSystem. */
658 class BS_CORE_EXPORT ParticleSystem final : public CoreObject, public SceneActor, public INonCopyable
659 {
660 public:
661 ~ParticleSystem();
662
663 /** @copydoc bs::ParticleSystem::setSettings */
664 const ParticleSystemSettings& getSettings() const { return mSettings; }
665
666 /** @copydoc bs::ParticleSystem::setGpuSimulationSettings */
667 const ParticleGpuSimulationSettings& getGpuSimulationSettings() const { return mGpuSimulationSettings; }
668
669 /**
670 * Determines the layer bitfield that controls whether a system is considered visible in a specific camera.
671 * Layer must match camera layer in order for the camera to render the component.
672 */
673 void setLayer(UINT64 layer);
674
675 /** @copydoc setLayer() */
676 UINT64 getLayer() const { return mLayer; }
677
678 /** Sets an ID that can be used for uniquely identifying this object by the renderer. */
679 void setRendererId(UINT32 id) { mRendererId = id; }
680
681 /** Retrieves an ID that can be used for uniquely identifying this object by the renderer. */
682 UINT32 getRendererId() const { return mRendererId; }
683
684 /**
685 * Returns an ID that uniquely identifies the particle system. Can be used for locating evaluated particle
686 * system render data in the structure output by the ParticlesManager.
687 */
688 UINT32 getId() const { return mId; }
689
690 /** @copydoc CoreObject::initialize */
691 void initialize() override;
692 private:
693 friend class bs::ParticleSystem;
694
695 ParticleSystem(UINT32 id)
696 :mId(id)
697 { }
698
699 /** @copydoc CoreObject::syncToCore */
700 void syncToCore(const CoreSyncData& data) override;
701
702 UINT32 mRendererId = 0;
703 UINT32 mId;
704
705 ParticleSystemSettings mSettings;
706 ParticleGpuSimulationSettings mGpuSimulationSettings;
707 UINT64 mLayer = 1;
708 };
709 }
710
711 /** @} */
712}
713