2025-02-17 23:17:30 -06:00

230 lines
7.9 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#ifndef _PARTICLEEMITTER_H_
#define _PARTICLEEMITTER_H_
#ifndef _GAMEBASE_H_
#include "game/gameBase.h"
#endif
#ifndef _COLOR_H_
#include "core/color.h"
#endif
//-------------------------------------- Engine initialization...
//
namespace ParticleEngine {
enum ParticleConsts
{
PC_COLOR_KEYS = 4,
PC_SIZE_KEYS = 4,
};
/// Initalize the particle engine
void init();
/// Destroy the particle engine
void destroy();
extern Point3F windVelocity; ///< Global wind velocity for all particles
/// Sets the wind velocity for all particles
/// @param vel Velocity
inline void setWindVelocity(const Point3F & vel) { windVelocity = vel; }
/// Returns the wind velocity
inline Point3F getWindVelocity() { return windVelocity; }
}
//--------------------------------------------------------------------------
//-------------------------------------- The data and the Emitter class
// are all that the game should deal
// with (other than initializing the
// global engine pointer of course)
//
struct Particle;
class ParticleData;
//--------------------------------------
class ParticleEmitterData : public GameBaseData
{
typedef GameBaseData Parent;
public:
ParticleEmitterData();
DECLARE_CONOBJECT(ParticleEmitterData);
static void initPersistFields();
void packData(BitStream* stream);
void unpackData(BitStream* stream);
bool preload(bool server, char errorBuffer[256]);
bool onAdd();
bool loadParameters();
bool reload();
public:
S32 ejectionPeriodMS; ///< Time, in Miliseconds, between particle ejection
S32 periodVarianceMS; ///< Varience in ejection peroid between 0 and n
F32 ejectionVelocity; ///< Ejection velocity
F32 velocityVariance; ///< Variance for velocity between 0 and n
F32 ejectionOffset; ///< Z offset from emitter point to eject from
F32 thetaMin; ///< Minimum angle, from the horizontal plane, to eject from
F32 thetaMax; ///< Maximum angle, from the horizontal plane, to eject from
F32 phiReferenceVel; ///< Reference angle, from the verticle plane, to eject from
F32 phiVariance; ///< Varience from the reference angle, from 0 to n
U32 lifetimeMS; ///< Lifetime of particles
U32 lifetimeVarianceMS; ///< Varience in lifetime from 0 to n
bool overrideAdvance; ///<
bool orientParticles; ///< Particles always face the screen
bool orientOnVelocity; ///< Particles face the screen at the start
bool useEmitterSizes; ///< Use emitter specified sizes instead of datablock sizes
bool useEmitterColors; ///< Use emitter specified colors instead of datablock colors
StringTableEntry particleString; ///< Used to load particle data directly from a string
Vector<ParticleData*> particleDataBlocks; ///< Datablocks for particle emissions
Vector<U32> dataBlockIds; ///< Datablock IDs which corospond to the particleDataBlocks
};
DECLARE_CONSOLETYPE(ParticleEmitterData)
//--------------------------------------
class ParticleEmitter : public GameBase
{
typedef GameBase Parent;
friend class PEngine;
public:
ParticleEmitter();
~ParticleEmitter();
/// Sets sizes of particles based on sizelist provided
/// @param sizeList List of sizes
void setSizes( F32 *sizeList );
/// Sets colors for particles based on color list provided
/// @param colorList List of colors
void setColors( ColorF *colorList );
ParticleEmitterData *getDataBlock(){ return mDataBlock; }
bool onNewDataBlock(GameBaseData* dptr);
/// By default, a particle renderer will wait for it's owner to delete it. When this
/// is turned on, it will delete itself as soon as it's particle count drops to zero.
void deleteWhenEmpty();
/// @name Particle Emission
/// Main interface for creating particles. The emitter does _not_ track changes
/// in axis or velocity over the course of a single update, so this should be called
/// at a fairly fine grain. The emitter will potentially track the last particle
/// to be created into the next call to this function in order to create a uniformly
/// random time distribution of the particles. If the object to which the emitter is
/// attached is in motion, it should try to ensure that for call (n+1) to this
/// function, start is equal to the end from call (n). This will ensure a uniform
/// spatial distribution.
/// @{
void emitParticles(const Point3F& start,
const Point3F& end,
const Point3F& axis,
const Point3F& velocity,
const U32 numMilliseconds);
void emitParticles(const Point3F& point,
const bool useLastPosition,
const Point3F& axis,
const Point3F& velocity,
const U32 numMilliseconds);
void emitParticles(const Point3F& rCenter,
const Point3F& rNormal,
const F32 radius,
const Point3F& velocity,
S32 count);
/// @}
virtual void setTransform(const MatrixF & mat);
protected:
/// @name Internal interface
/// @{
/// Adds a particle
/// @param pos Initial position of particle
/// @param axis
/// @param vel Initial velocity
/// @param axisx
void addParticle(const Point3F &pos, const Point3F &axis, const Point3F &vel, const Point3F &axisx);
/// Renders a particle facing the camera with a spin factor
/// @param part Particle
/// @param basePnts Base points for the quad the particle is rendered on
/// @param camView Camera view matrix
/// @param spinFactor 0.0-1.0 modifyer for
void renderBillboardParticle( Particle &part, Point3F *basePnts, MatrixF &camView, F32 spinFactor );
/// Renders a particle which will face the camera but spin itself to look
/// like it is facing a particular velocity.
/// @param part Particle
/// @param camPos Camera position
void renderOrientedParticle( Particle &part, const Point3F &camPos );
/// Updates the bounding box for the particle system
bool updateBBox(const Point3F &position);
/// @}
protected:
bool onAdd();
void onRemove();
void processTick(const Move *move);
void advanceTime(F32 dt);
// Rendering
protected:
bool prepRenderImage(SceneState *state, const U32 stateKey, const U32 startZone, const bool modifyBaseZoneState);
void renderObject(SceneState *state, SceneRenderImage *image);
// PEngine interface
private:
/// Removes the provided particle from the system and lets the caller of the
/// function assume control of it
/// @param part Particle
void stealParticle(Particle *part);
private:
ParticleEmitterData* mDataBlock;
/// This is used so we only update our transform/bounding box
/// on ticks, to minimize calls to setTransform.
bool mNeedTransformUpdate;
Particle* mParticleListHead;
U32 mInternalClock;
U32 mNextParticleTime;
Point3F mLastPosition;
bool mHasLastPosition;
bool mDeleteWhenEmpty;
bool mDeleteOnTick;
S32 mLifetimeMS;
S32 mElapsedTimeMS;
F32 sizes[ParticleEngine::PC_SIZE_KEYS];
ColorF colors[ParticleEngine::PC_COLOR_KEYS];
};
#endif // _H_PARTICLEEMITTER