particle_system.hpp 4.28 KB
Newer Older
1
2
3
#pragma once

#include <mirrage/asset/asset_manager.hpp>
4
#include <mirrage/ecs/entity_manager.hpp>
5
6
7
8
9
10
11
#include <mirrage/graphic/texture.hpp>
#include <mirrage/utils/sf2_glm.hpp>
#include <mirrage/utils/units.hpp>

#include <glm/vec3.hpp>
#include <sf2/sf2.hpp>

12
13
14
#include <random>
#include <tuple>

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

namespace mirrage::renderer {

	enum class Particle_blend_mode { unlit };
	sf2_enumDef(Particle_blend_mode, unlit);

	enum class Particle_emitter_shape { sphere };
	sf2_enumDef(Particle_emitter_shape, sphere);

	template <typename T = std::uint8_t>
	struct Particle_color {
		T hue;
		T saturation;
		T value;
		T alpha;
	};
	sf2_structDef(Particle_color<float>, hue, saturation, value, alpha);
	sf2_structDef(Particle_color<std::uint8_t>, hue, saturation, value, alpha);

	struct Particle_emitter_config {
		float time = 0;

		float spawn_rate_mean     = 10.f;
		float spawn_rate_variance = 1.f;

		Particle_color<float> color_mean            = {1, 1, 1, 1};
		Particle_color<float> color_variance        = {0, 0, 0, 0};
		Particle_color<float> color_change_mean     = {0, 0, 0, 0};
		Particle_color<float> color_change_variance = {0, 0, 0, 0};

		float size_mean            = 0.1f;
		float size_variance        = 0.f;
		float size_change_mean     = 0.f;
		float size_change_variance = 0.f;

		float rotation_mean            = 0.1f;
		float rotation_variance        = 0.1f;
		float rotation_change_mean     = 0.f;
		float rotation_change_variance = 0.f;

		float ttl_mean     = 1.f;
		float ttl_variance = 0.f;

58
59
		float velocity_mean     = 1.f;
		float velocity_variance = 0.f;
60
61
62
63

		Particle_blend_mode    blend      = Particle_blend_mode::unlit;
		Particle_emitter_shape shape      = Particle_emitter_shape::sphere;
		glm::vec3              shape_size = glm::vec3(1, 1, 1);
64
65
66
67
68

		float drag = 0.f;

		// returns offset and direction
		auto calc_offset(std::mt19937&) -> std::tuple<glm::vec3, glm::vec3>;
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
	};
	sf2_structDef(Particle_emitter_config,
	              time,
	              spawn_rate_mean,
	              spawn_rate_variance,
	              color_mean,
	              color_variance,
	              color_change_mean,
	              color_change_variance,
	              size_mean,
	              size_variance,
	              size_change_mean,
	              size_change_variance,
	              rotation_mean,
	              rotation_variance,
	              rotation_change_mean,
	              rotation_change_variance,
	              ttl_mean,
	              ttl_variance,
	              velocity_mean,
	              velocity_variance,
	              blend,
	              shape,
92
93
	              shape_size,
	              drag);
94
95
96
97
98
99


	class Particle_emitter {
	  public:
		Particle_emitter(graphic::Texture_ptr                 texture,
		                 std::vector<Particle_emitter_config> keyframes,
100
101
		                 std::size_t                          capacity,
		                 util::maybe<ecs::Entity_facet>       follow_entity = {});
102

103
104
105
106
107
108
109
110
111
		void position(glm::vec3 p)
		{
			_center_position = p;
			_follow_entity   = {};
		}
		void follow(ecs::Entity_facet f) { _follow_entity = f; }

		void update(util::Time dt, bool emit_new, std::mt19937&);
		auto dead() const -> bool { return _positions.empty(); }
112
113
114
115
116
117
118
119
120

		auto active() const noexcept { return _active; }
		void enable() { _active = true; }
		void disable() { _active = false; }

	  private:
		graphic::Texture_ptr                 _texture;
		std::vector<Particle_emitter_config> _config_keyframes;

121
122
123
124
125
126
127
128
129
130
131
		std::vector<glm::vec3>     _positions;
		std::vector<std::uint32_t> _seeds;
		std::vector<float>         _creation_times;
		std::vector<float>         _ttls;
		std::vector<glm::vec3>     _velocities;

		std::vector<std::int_fast32_t> _dead_indices;

		util::Time _time     = util::Time{0.f};
		float      _to_spawn = 0.f;
		bool       _active   = true;
132

133
134
		glm::vec3                      _center_position = {0, 0, 0};
		util::maybe<ecs::Entity_facet> _follow_entity;
135
136
137
138
	};

	class Particle_system {
	  public:
139
		Particle_system(asset::Asset_manager& assets);
140
141
142
143
144
145
146
147

		void add_emitter(std::shared_ptr<Particle_emitter>);
		auto add_emitter(asset::AID descriptor) -> std::shared_ptr<Particle_emitter>;

		void update(util::Time);

	  private:
		asset::Asset_manager& _assets;
148
		std::mt19937          _random_gen;
149
150
151
152
153

		std::vector<std::shared_ptr<Particle_emitter>> _emmitter;
		// TODO
	};
} // namespace mirrage::renderer