File: ParticleSource.h

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (405 lines) | stat: -rw-r--r-- 12,094 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
#ifndef PARTICLE_SOURCE_H
#define PARTICLE_SOURCE_H
#pragma once

#include "globalincs/pstypes.h"

#include "object/object.h"

#include "particle/particle.h"
#include "particle/ParticleEffect.h"

#include "io/timer.h"

#include <tl/optional.hpp>

struct weapon;

struct weapon_info;

// Forward declaration so we don't need weapons.h
enum class WeaponState: uint32_t;

namespace particle {
/**
 * The origin type
 */
enum class SourceOriginType {
	NONE, //!< Invalid origin
	VECTOR, //!< World-space offset
	BEAM, //!< A beam
	OBJECT, //!< An object
	SUBOBJECT, //!< A subobject
	TURRET, //!< A turret
	PARTICLE //!< A particle
};

class ParticleSource;

class ParticleEffect;

/**
 * @brief A source origin
 *
 * The SourceOrigin class encapsualtes the information about where a source is located. It allows a source to be
 * relative to an object or a particle and keeps track of whether the host objects are still valid.
 */
class SourceOrigin {
 private:
	SourceOriginType m_originType;

	struct {
		vec3d m_pos;

		// this is used only for vector-type sources, and is not used when the effect's parent is an object
		// when the parent is an object, we get the relevant orientation from the object, so that it stays updated
		// when the parent is an object, we get the relevant orientation from the object, so that it stays updated
		matrix m_host_orientation;

		object_h m_object;

		int m_subobject;

		int m_fire_pos;

		WeakParticlePtr m_particle;
	} m_origin;

	WeaponState m_weaponState;

	vec3d m_offset;

	vec3d m_velocity;

 public:
	/**
	 * @brief Initializes the origin with default values
	 */
	SourceOrigin();

	/**
	 * @brief Gets the current, global position of the origin
	 * 
	 * For object sources, can interpolate between object's current position and its position last frame
	 * 
	 * Be aware for beam sources this will give *random* points along its length
	 * 
	 * @param posOut The pointer where the location will be stored
	 * 
	 * @param interp For objects, the point's position between the current-frame
	 * and last-frame positions of the object, with 0.0 being current-frame and 1.0 being last-frame
	 */
	void getGlobalPosition(vec3d* posOut, float interp = 1.0f, tl::optional<vec3d> manual_offset = tl::nullopt) const;

	void getHostOrientation(matrix* matOut, bool allow_relative) const;

	inline SourceOriginType getType() const { return m_originType; }

	inline object* getObjectHost() const { return m_origin.m_object.objp_or_null(); }

	/**
	 * @brief Determines if the origin is valid
	 *
	 * This checks if the hosting object is valid or if the hosting particle is still valid.
	 *
	 * @return @c true if the origin is valid, @c false otherwise
	 */
	bool isValid() const;

	/**
	 * @brief Applies the information to a particle info
	 *
	 * This fills the provided &info with certain data from the origin, such as objnum/signature of an object origin,
	 * the scale and remaining lifetime of a particle origin, or simply the current global position of the origin
	 *
	 * @param info The particle_info this should be applied to
	 */
	void applyToParticleInfo(particle_info& info, bool allowRelative = false, float interp = 1.0f, tl::optional<vec3d> manual_offset = tl::nullopt) const;

	/**
	 * @brief Gets the velocity of the origin host
	 * @return The velocity of the host
	 */
	vec3d getVelocity() const;

	/**
	 * @brief Gets the current scale of the origin host, always 1 for non-particles
	 * @return The scale of the host
	 */
	float getScale() const;

	/**
	 * @brief Gets the remaining lifetime of the origin host, always -1.0 for non-particles
	 * @return The lifeleft of the host
	 */
	float getLifetime() const;

	/**
	 * @brief Sets the weapon state in which this origin is valid
	 * @param state The weapon state to use
	 */
	void setWeaponState(WeaponState state);

	/**
	 * @brief Moves the source to the specified world location
	 * @param pos The world position
	 */
	void moveTo(const vec3d* pos, const matrix* orientation = &vmd_identity_matrix);

	/**
	 * @brief Moves the source to the specified beam object
	 * @param objp The hosting beam
	 */
	void moveToBeam(const object* objp);

	/**
	 * @brief Moves the source to the specified object with an offset
	 * @param objp The hosting object
	 * @param offset The position relative to this object
	 */
	void moveToObject(const object* objp, const vec3d* offset);

		/**
	 * @brief Moves the source to the specified object with an offset
	 * @param objp The hosting object
	 * @param offset The position relative to this object
	 */
	void moveToSubobject(const object* objp, int subobject, const vec3d* offset);

	/**
	 * @brief Moves the source to the specified object with an offset
	 * @param objp The hosting object
	 * @param offset The position relative to this object
	 */
	void moveToTurret(const object* objp, int subobject, int fire_pos);

	/**
	 * @brief Moves the source to the specified particle
	 * @param weakParticlePtr The hosting particle
	 */
	void moveToParticle(const WeakParticlePtr& weakParticlePtr);

	/**
	* @brief Sets the velocity of the source, will not move the source, but particles created may inherit this velocity
	* @param vel The world velocity
	*/
	void setVelocity(const vec3d* vel);

	friend class ParticleSource;
};

/**
 * @brief The orientation of a particle source
 *
 * Currently only the forward direction vector is useful because the other vectors of the matrix are chosen pretty
 * arbitrarily. This also contains a normal vector if it was specified when creating the source.
 * 
 * A source's SourceOrientation is distinct from its host orientation. The host orientation is either defined in
 * SourceOrigin or gathered from the parent object, depending on host type. Host orientation is applied before position offset.
 * SourceOrientation is applied after position offset.
 * 
 * An orientation can be either relative or global. In relative mode all transforms should be relative to the host
 * object and its orientation. In global mode, all directions are in world-space,
 * and host orientation is overridden completely (though it will still affect the orientation of position offsets).
 * 
 * Normals are always in world-space.
 * 
 */
class SourceOrientation {
 private:
	matrix m_orientation;

	bool m_hasNormal = false;
	vec3d m_normal;

	// By default the orientation of a source is relative to the host
	bool m_isRelative = true;

 public:
	SourceOrientation();

	/**
	 * @brief Sets the direction from a vector
	 *
	 * The vector doesn't have to be normalized before passing it to this function.
	 *
	 * @param vec The vector to create the matrix from
	 */
	void setFromVector(const vec3d& vec, bool relative = false);

	/**
	 * @brief Sets the direction from an already normalized vector
	 *
	 * @param vec The normalized vector
	 */
	void setFromNormalizedVector(const vec3d& vec, bool relative = false);

	void setNormal(const vec3d& normal);

	void setFromMatrix(const matrix& mat, bool relative = false);

	vec3d getDirectionVector(const SourceOrigin* origin, bool allow_relative = false) const;

	bool isRelative() const { return m_isRelative; }

	/**
	 * @brief Gets the normal of this orientation
	 * @param outNormal The pointer where the normal will be written
	 * @return @c true if there was a normal, @c false otherwise
	 */
	bool getNormal(vec3d* outNormal) const;

	inline const matrix* getMatrix() const { return &m_orientation; }

	friend class ParticleSource;
};

/**
 * @brief Contains information about the timing of a source
 *
 * This can be used to control when a source is active and when it will be deleted. Since a source can be active at a
 * later time the timing goes through three stages. In the first state the source is created but not active. #isActive()
 * returns false but #isFinished() also return false. When it activates #isActive() will return true while #isFinished()
 * stays @c false. Then #isActive() will be @c false and #isFinished() will be @c true. At this point the source is
 * considered to have expired and it will be removed the next time it is processed.
 */
class SourceTiming {
 private:
	int m_creationTimestamp;
	int m_nextCreation; //! The next time the source should generate a particle. Controlled by the effect of the source.

	int m_beginTimestamp;
	int m_endTimestamp;

 public:
	SourceTiming();

	void setCreationTimestamp(int time);

	int getCreationTime() const { return m_creationTimestamp; }

	/**
	 * @brief Sets when the source is active
	 *
	 * The source will be active between the specified begin and end times
	 *
	 * @param begin The timestamp when the source will begin to be active
	 * @param end The timestamp when the source will not be active anymore
	 */
	void setLifetime(int begin, int end);

	/**
	 * @brief Determines if the source is currently active
	 * @return @c true if the source is active
	 */
	bool isActive() const;

	/**
	 * @brief Determines if the source has expired
	 * @return @c true if the source has expired.
	 */
	bool isFinished() const;

	/**
	 * @brief Gets the progress of the source through its active time.
	 *
	 * If the source is not active or if the timestamps are not valid then -1 is returned
	 *
	 * @return The progress of the source through its lifetime
	 */
	float getLifeTimeProgress() const;

	int getNextCreationTime() const;

	/**
	 * @brief Determine if the timestamp for the next particle creation has expired
	 * @return @c true if the timestamp has expired, false otherwise
	 */
	bool nextCreationTimeExpired() const;

	/**
	 * @brief Move the internal timestamp for the next creation forward
	 *
	 * Use this for achieving a consistent amount of created particles regardless of FPS by setting time_diff_ms to a
	 * constant time and call nextCreationTimeExpired() until that returns false. Then all particles for that frame have
	 * been created.
	 *
	 * @param time_diff_ms
	 */
	void incrementNextCreationTime(int time_diff_ms);

	friend class ParticleSource;
};

/**
 * @brief A particle source
 *
 * A particle source contains the information about where and for how long particles are created. A particle effect uses
 * this information to create new particles. A particle source has not effect-specific information which means that an
 * effect can only use the information contained in this object.
 *
 * @ingroup particleSystems
 */
class ParticleSource {
 private:
	SourceOrigin m_origin; //!< The current position of this particle source

	SourceOrientation m_effectOrientation; //!< The orientation of the particle source

	SourceTiming m_timing; //!< The time informations of the particle source

	ParticleEffect* m_effect; //!< The effect that is assigned to this source

	size_t m_processingCount; //!< The number of times this effect has been processed

	void initializeThrusterOffset(weapon* wp, weapon_info* wip);
 public:
	ParticleSource();

	inline const ParticleEffect* getEffect() const { return m_effect; }

	inline ParticleEffect* getEffect() { return m_effect; }

	inline void setEffect(ParticleEffect* eff) {
		Assert(eff != nullptr);
		m_effect = eff;
	}

	inline const SourceOrigin* getOrigin() const { return &m_origin; }

	inline SourceOrigin* getOrigin() { return &m_origin; }

	inline const SourceOrientation* getOrientation() const { return &m_effectOrientation; }

	inline SourceOrientation* getOrientation() { return &m_effectOrientation; }

	inline const SourceTiming* getTiming() const { return &m_timing; }

	inline SourceTiming* getTiming() { return &m_timing; }

	inline size_t getProcessingCount() const { return m_processingCount; }

	/**
	 * @brief Finishes the creation of a particle source
	 *
	 * This is used to initialize some status that is only available after everything has been set up.
	 */
	void finishCreation();

	/**
	 * @brief Does one processing step for this source
	 * @return @c true if the source should continue to be processed
	 */
	bool process();

	/**
	 * @brief Determines if the source is valid
	 * @return @c true if the source is valid, @c false otherwise.
	 */
	bool isValid() const;
};
}


#endif // PARTICLE_SOURCE_H