1/**************************************************************************/
2/* cpu_particles_3d.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef CPU_PARTICLES_3D_H
32#define CPU_PARTICLES_3D_H
33
34#include "scene/3d/visual_instance_3d.h"
35
36class CPUParticles3D : public GeometryInstance3D {
37private:
38 GDCLASS(CPUParticles3D, GeometryInstance3D);
39
40public:
41 enum DrawOrder {
42 DRAW_ORDER_INDEX,
43 DRAW_ORDER_LIFETIME,
44 DRAW_ORDER_VIEW_DEPTH,
45 DRAW_ORDER_MAX
46 };
47
48 enum Parameter {
49 PARAM_INITIAL_LINEAR_VELOCITY,
50 PARAM_ANGULAR_VELOCITY,
51 PARAM_ORBIT_VELOCITY,
52 PARAM_LINEAR_ACCEL,
53 PARAM_RADIAL_ACCEL,
54 PARAM_TANGENTIAL_ACCEL,
55 PARAM_DAMPING,
56 PARAM_ANGLE,
57 PARAM_SCALE,
58 PARAM_HUE_VARIATION,
59 PARAM_ANIM_SPEED,
60 PARAM_ANIM_OFFSET,
61 PARAM_MAX
62 };
63
64 enum ParticleFlags {
65 PARTICLE_FLAG_ALIGN_Y_TO_VELOCITY,
66 PARTICLE_FLAG_ROTATE_Y,
67 PARTICLE_FLAG_DISABLE_Z,
68 PARTICLE_FLAG_MAX
69 };
70
71 enum EmissionShape {
72 EMISSION_SHAPE_POINT,
73 EMISSION_SHAPE_SPHERE,
74 EMISSION_SHAPE_SPHERE_SURFACE,
75 EMISSION_SHAPE_BOX,
76 EMISSION_SHAPE_POINTS,
77 EMISSION_SHAPE_DIRECTED_POINTS,
78 EMISSION_SHAPE_RING,
79 EMISSION_SHAPE_MAX
80 };
81
82private:
83 bool emitting = false;
84 bool active = false;
85
86 struct Particle {
87 Transform3D transform;
88 Color color;
89 real_t custom[4] = {};
90 Vector3 velocity;
91 bool active = false;
92 real_t angle_rand = 0.0;
93 real_t scale_rand = 0.0;
94 real_t hue_rot_rand = 0.0;
95 real_t anim_offset_rand = 0.0;
96 Color start_color_rand;
97 double time = 0.0;
98 double lifetime = 0.0;
99 Color base_color;
100
101 uint32_t seed = 0;
102 };
103
104 double time = 0.0;
105 double frame_remainder = 0.0;
106 int cycle = 0;
107 bool redraw = false;
108
109 RID multimesh;
110
111 Vector<Particle> particles;
112 Vector<float> particle_data;
113 Vector<int> particle_order;
114
115 struct SortLifetime {
116 const Particle *particles = nullptr;
117
118 bool operator()(int p_a, int p_b) const {
119 return particles[p_a].time > particles[p_b].time;
120 }
121 };
122
123 struct SortAxis {
124 const Particle *particles = nullptr;
125 Vector3 axis;
126 bool operator()(int p_a, int p_b) const {
127 return axis.dot(particles[p_a].transform.origin) < axis.dot(particles[p_b].transform.origin);
128 }
129 };
130
131 //
132
133 bool one_shot = false;
134
135 double lifetime = 1.0;
136 double pre_process_time = 0.0;
137 real_t explosiveness_ratio = 0.0;
138 real_t randomness_ratio = 0.0;
139 double lifetime_randomness = 0.0;
140 double speed_scale = 1.0;
141 bool local_coords = false;
142 int fixed_fps = 0;
143 bool fractional_delta = true;
144
145 Transform3D inv_emission_transform;
146
147 SafeFlag can_update;
148
149 DrawOrder draw_order = DRAW_ORDER_INDEX;
150
151 Ref<Mesh> mesh;
152
153 ////////
154
155 Vector3 direction = Vector3(1, 0, 0);
156 real_t spread = 45.0;
157 real_t flatness = 0.0;
158
159 real_t parameters_min[PARAM_MAX] = {};
160 real_t parameters_max[PARAM_MAX] = {};
161
162 Ref<Curve> curve_parameters[PARAM_MAX];
163 Color color = Color(1, 1, 1, 1);
164 Ref<Gradient> color_ramp;
165 Ref<Gradient> color_initial_ramp;
166
167 bool particle_flags[PARTICLE_FLAG_MAX] = {};
168
169 EmissionShape emission_shape = EMISSION_SHAPE_POINT;
170 real_t emission_sphere_radius = 1.0;
171 Vector3 emission_box_extents = Vector3(1, 1, 1);
172 Vector<Vector3> emission_points;
173 Vector<Vector3> emission_normals;
174 Vector<Color> emission_colors;
175 int emission_point_count = 0;
176 Vector3 emission_ring_axis;
177 real_t emission_ring_height = 0.0;
178 real_t emission_ring_radius = 0.0;
179 real_t emission_ring_inner_radius = 0.0;
180
181 Ref<Curve> scale_curve_x;
182 Ref<Curve> scale_curve_y;
183 Ref<Curve> scale_curve_z;
184 bool split_scale = false;
185
186 Vector3 gravity = Vector3(0, -9.8, 0);
187
188 void _update_internal();
189 void _particles_process(double p_delta);
190 void _update_particle_data_buffer();
191
192 Mutex update_mutex;
193
194 void _update_render_thread();
195
196 void _set_redraw(bool p_redraw);
197
198protected:
199 static void _bind_methods();
200 void _notification(int p_what);
201 void _validate_property(PropertyInfo &p_property) const;
202
203public:
204 AABB get_aabb() const override;
205
206 void set_emitting(bool p_emitting);
207 void set_amount(int p_amount);
208 void set_lifetime(double p_lifetime);
209 void set_one_shot(bool p_one_shot);
210 void set_pre_process_time(double p_time);
211 void set_explosiveness_ratio(real_t p_ratio);
212 void set_randomness_ratio(real_t p_ratio);
213 void set_lifetime_randomness(double p_random);
214 void set_use_local_coordinates(bool p_enable);
215 void set_speed_scale(double p_scale);
216
217 bool is_emitting() const;
218 int get_amount() const;
219 double get_lifetime() const;
220 bool get_one_shot() const;
221 double get_pre_process_time() const;
222 real_t get_explosiveness_ratio() const;
223 real_t get_randomness_ratio() const;
224 double get_lifetime_randomness() const;
225 bool get_use_local_coordinates() const;
226 double get_speed_scale() const;
227
228 void set_fixed_fps(int p_count);
229 int get_fixed_fps() const;
230
231 void set_fractional_delta(bool p_enable);
232 bool get_fractional_delta() const;
233
234 void set_draw_order(DrawOrder p_order);
235 DrawOrder get_draw_order() const;
236
237 void set_mesh(const Ref<Mesh> &p_mesh);
238 Ref<Mesh> get_mesh() const;
239
240 ///////////////////
241
242 void set_direction(Vector3 p_direction);
243 Vector3 get_direction() const;
244
245 void set_spread(real_t p_spread);
246 real_t get_spread() const;
247
248 void set_flatness(real_t p_flatness);
249 real_t get_flatness() const;
250
251 void set_param_min(Parameter p_param, real_t p_value);
252 real_t get_param_min(Parameter p_param) const;
253
254 void set_param_max(Parameter p_param, real_t p_value);
255 real_t get_param_max(Parameter p_param) const;
256
257 void set_param_curve(Parameter p_param, const Ref<Curve> &p_curve);
258 Ref<Curve> get_param_curve(Parameter p_param) const;
259
260 void set_color(const Color &p_color);
261 Color get_color() const;
262
263 void set_color_ramp(const Ref<Gradient> &p_ramp);
264 Ref<Gradient> get_color_ramp() const;
265
266 void set_color_initial_ramp(const Ref<Gradient> &p_ramp);
267 Ref<Gradient> get_color_initial_ramp() const;
268
269 void set_particle_flag(ParticleFlags p_particle_flag, bool p_enable);
270 bool get_particle_flag(ParticleFlags p_particle_flag) const;
271
272 void set_emission_shape(EmissionShape p_shape);
273 void set_emission_sphere_radius(real_t p_radius);
274 void set_emission_box_extents(Vector3 p_extents);
275 void set_emission_points(const Vector<Vector3> &p_points);
276 void set_emission_normals(const Vector<Vector3> &p_normals);
277 void set_emission_colors(const Vector<Color> &p_colors);
278 void set_emission_ring_axis(Vector3 p_axis);
279 void set_emission_ring_height(real_t p_height);
280 void set_emission_ring_radius(real_t p_radius);
281 void set_emission_ring_inner_radius(real_t p_radius);
282 void set_scale_curve_x(Ref<Curve> p_scale_curve);
283 void set_scale_curve_y(Ref<Curve> p_scale_curve);
284 void set_scale_curve_z(Ref<Curve> p_scale_curve);
285 void set_split_scale(bool p_split_scale);
286
287 EmissionShape get_emission_shape() const;
288 real_t get_emission_sphere_radius() const;
289 Vector3 get_emission_box_extents() const;
290 Vector<Vector3> get_emission_points() const;
291 Vector<Vector3> get_emission_normals() const;
292 Vector<Color> get_emission_colors() const;
293 Vector3 get_emission_ring_axis() const;
294 real_t get_emission_ring_height() const;
295 real_t get_emission_ring_radius() const;
296 real_t get_emission_ring_inner_radius() const;
297 Ref<Curve> get_scale_curve_x() const;
298 Ref<Curve> get_scale_curve_y() const;
299 Ref<Curve> get_scale_curve_z() const;
300 bool get_split_scale();
301
302 void set_gravity(const Vector3 &p_gravity);
303 Vector3 get_gravity() const;
304
305 PackedStringArray get_configuration_warnings() const override;
306
307 void restart();
308
309 void convert_from_particles(Node *p_particles);
310
311 CPUParticles3D();
312 ~CPUParticles3D();
313};
314
315VARIANT_ENUM_CAST(CPUParticles3D::DrawOrder)
316VARIANT_ENUM_CAST(CPUParticles3D::Parameter)
317VARIANT_ENUM_CAST(CPUParticles3D::ParticleFlags)
318VARIANT_ENUM_CAST(CPUParticles3D::EmissionShape)
319
320#endif // CPU_PARTICLES_3D_H
321