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 | |
17 | namespace 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 | |