MegaGlest/source/shared_lib/include/graphics/particle.h

673 lines
19 KiB
C++

// ==============================================================
// This file is part of Glest Shared Library (www.glest.org)
//
// Copyright (C) 2001-2008 Martiño Figueroa
//
// You can redistribute this code and/or modify it under
// the terms of the GNU General Public License as published
// by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version
// ==============================================================
#ifndef _SHARED_GRAPHICS_PARTICLE_H_
#define _SHARED_GRAPHICS_PARTICLE_H_
#include <list>
#include <cassert>
#include "vec.h"
#include "pixmap.h"
#include "texture_manager.h"
#include "randomgen.h"
#include "xml_parser.h"
#include "leak_dumper.h"
#include "interpolation.h"
using std::list;
using Shared::Util::RandomGen;
using Shared::Xml::XmlNode;
namespace Shared{ namespace Graphics{
class ParticleSystem;
class FireParticleSystem;
class UnitParticleSystem;
class RainParticleSystem;
class SnowParticleSystem;
class ProjectileParticleSystem;
class SplashParticleSystem;
class ParticleRenderer;
class ModelRenderer;
class Model;
// =====================================================
// class Particle
// =====================================================
class Particle {
public:
//attributes
Vec3f pos;
Vec3f lastPos;
Vec3f speed;
float speedUpRelative;
Vec3f speedUpConstant;
Vec3f accel;
Vec4f color;
float size;
int energy;
public:
Particle() {
speedUpRelative = 0;
size = 0;
energy = 0;
}
//get
Vec3f getPos() const {return pos;}
Vec3f getLastPos() const {return lastPos;}
Vec3f getSpeed() const {return speed;}
Vec3f getAccel() const {return accel;}
Vec4f getColor() const {return color;}
float getSize() const {return size;}
int getEnergy() const {return energy;}
void saveGame(XmlNode *rootNode);
void loadGame(const XmlNode *rootNode);
};
// =====================================================
// class ParticleObserver
// =====================================================
class ParticleObserver {
public:
virtual ~ParticleObserver(){};
virtual void update(ParticleSystem *particleSystem)= 0;
virtual void saveGame(XmlNode *rootNode) = 0;
virtual void loadGame(const XmlNode *rootNode, void *genericData) = 0;
};
class ParticleOwner {
public:
virtual ~ParticleOwner() {}
virtual void end(ParticleSystem *particleSystem)= 0;
virtual void logParticleInfo(string info)= 0;
};
class ParticleSystemTypeInterface {
public:
ParticleSystemTypeInterface() {};
virtual ~ParticleSystemTypeInterface() {};
virtual bool getMinmaxEnabled() const = 0;
virtual int getMinHp() const = 0;
virtual int getMaxHp() const = 0;
virtual bool getMinmaxIsPercent() const = 0;
};
// =====================================================
// class ParticleSystem
// =====================================================
class ParticleSystem {
public:
enum State {
sPause, // No updates
sPlay,
sFade // No new particles
};
enum BlendMode {
bmOne,
bmOneMinusAlpha
};
enum ParticleSystemType {
pst_All,
pst_FireParticleSystem,
pst_UnitParticleSystem,
pst_RainParticleSystem,
pst_SnowParticleSystem,
pst_ProjectileParticleSystem,
pst_SplashParticleSystem,
};
protected:
std::vector<Particle> particles;
RandomGen random;
BlendMode blendMode;
State state;
bool active;
bool visible;
int aliveParticleCount;
int particleCount;
string textureFileLoadDeferred;
int textureFileLoadDeferredSystemId;
Texture::Format textureFileLoadDeferredFormat;
int textureFileLoadDeferredComponents;
Texture *texture;
Vec3f pos;
Vec4f color;
Vec4f colorNoEnergy;
float emissionRate;
float emissionState;
int maxParticleEnergy;
int varParticleEnergy;
float particleSize;
float speed;
float speedUpRelative;
float speedUpConstant;
Vec3f factionColor;
bool teamcolorNoEnergy;
bool teamcolorEnergy;
int alternations;
int particleSystemStartDelay;
ParticleObserver *particleObserver;
ParticleOwner *particleOwner;
public:
//conmstructor and destructor
ParticleSystem(int particleCount);
virtual ~ParticleSystem();
virtual ParticleSystemType getParticleSystemType() const = 0;
//public
virtual void update();
virtual void render(ParticleRenderer *pr, ModelRenderer *mr);
//get
State getState() const {return state;}
BlendMode getBlendMode() const {return blendMode;}
Texture *getTexture() const {return texture;}
Vec3f getPos() const {return pos;}
Particle *getParticle(int i) {return &particles[i];}
const Particle *getParticle(int i) const {return &particles[i];}
int getAliveParticleCount() const {return aliveParticleCount;}
bool getActive() const {return active;}
virtual bool getVisible() const {return visible;}
virtual string getTextureFileLoadDeferred();
virtual int getTextureFileLoadDeferredSystemId();
virtual Texture::Format getTextureFileLoadDeferredFormat();
virtual int getTextureFileLoadDeferredComponents();
//set
virtual void setState(State state);
void setTexture(Texture *texture);
virtual void setPos(Vec3f pos);
void setColor(Vec4f color);
void setColorNoEnergy(Vec4f color);
void setEmissionRate(float emissionRate);
void setMaxParticleEnergy(int maxParticleEnergy);
void setVarParticleEnergy(int varParticleEnergy);
void setParticleSize(float particleSize);
void setSpeed(float speed);
void setSpeedUpRelative(float speedUpRelative);
void setSpeedUpConstant(float speedUpConstant);
virtual void setActive(bool active);
void setObserver(ParticleObserver *particleObserver);
virtual void setVisible(bool visible);
void setBlendMode(BlendMode blendMode) {this->blendMode= blendMode;}
void setTeamcolorNoEnergy(bool teamcolorNoEnergy) {this->teamcolorNoEnergy= teamcolorNoEnergy;}
void setTeamcolorEnergy(bool teamcolorEnergy) {this->teamcolorEnergy= teamcolorEnergy;}
void setAlternations(int alternations) {this->alternations= alternations;}
void setParticleSystemStartDelay(int delay) {this->particleSystemStartDelay= delay;}
virtual void setFactionColor(Vec3f factionColor);
static BlendMode strToBlendMode(const string &str);
//misc
virtual void fade();
int isEmpty() const;
virtual void setParticleOwner(ParticleOwner *particleOwner) { this->particleOwner = particleOwner;}
virtual ParticleOwner * getParticleOwner() { return this->particleOwner;}
virtual void callParticleOwnerEnd(ParticleSystem *particleSystem);
//children
virtual int getChildCount() { return 0; }
virtual ParticleSystem* getChild(int i);
virtual string toString() const;
virtual void saveGame(XmlNode *rootNode);
virtual void loadGame(const XmlNode *rootNode);
virtual Checksum getCRC();
protected:
//protected
Particle *createParticle();
void killParticle(Particle *p);
//virtual protected
virtual void initParticle(Particle *p, int particleIndex);
virtual void updateParticle(Particle *p);
virtual bool deathTest(Particle *p);
};
// =====================================================
// class FireParticleSystem
// =====================================================
class FireParticleSystem: public ParticleSystem{
private:
float radius;
Vec3f windSpeed;
public:
FireParticleSystem(int particleCount= 2000);
virtual ParticleSystemType getParticleSystemType() const { return pst_FireParticleSystem;}
//virtual
virtual void initParticle(Particle *p, int particleIndex);
virtual void updateParticle(Particle *p);
//set params
void setRadius(float radius);
void setWind(float windAngle, float windSpeed);
virtual void saveGame(XmlNode *rootNode);
virtual void loadGame(const XmlNode *rootNode);
virtual string toString() const;
virtual Checksum getCRC();
};
// =====================================================
// class GameParticleSystem
/// base-class for unit and attack systems
// =====================================================
class UnitParticleSystem;
class GameParticleSystem: public ParticleSystem{
public:
enum Primitive{
pQuad,
pLine,
pLineAlpha
};
static Primitive strToPrimitive(const string &str);
virtual ~GameParticleSystem();
int getChildCount();
ParticleSystem* getChild(int i);
void addChild(UnitParticleSystem* child);
void removeChild(UnitParticleSystem* child);
void setPos(Vec3f pos);
void setOffset(Vec3f offset);
void setModel(Model *model) {this->model= model;}
virtual void render(ParticleRenderer *pr, ModelRenderer *mr);
float getTween() { return tween; } // 0.0 -> 1.0 for animation of model
Model *getModel() const {return model;}
virtual string getModelFileLoadDeferred();
void setPrimitive(Primitive primitive) {this->primitive= primitive;}
Vec3f getDirection() const {return direction;}
void setModelCycle(float modelCycle) {this->modelCycle= modelCycle;}
virtual void saveGame(XmlNode *rootNode);
virtual void loadGame(const XmlNode *rootNode);
virtual string toString() const;
virtual Checksum getCRC();
protected:
typedef std::vector<UnitParticleSystem*> Children;
Children children;
Primitive primitive;
string modelFileLoadDeferred;
Model *model;
float modelCycle;
Vec3f offset;
Vec3f direction;
float tween;
GameParticleSystem(int particleCount);
void positionChildren();
void setTween(float relative,float absolute);
};
// =====================================================
// class UnitParticleSystem
// =====================================================
class UnitParticleSystem: public GameParticleSystem{
public:
static bool isNight;
static Vec3f lightColor;
private:
float radius;
float minRadius;
Vec3f windSpeed;
Vec3f cRotation;
Vec3f fixedAddition;
Vec3f oldPosition;
bool energyUp;
float startTime;
float endTime;
ParticleSystemTypeInterface *particleSystemType;
public:
enum Shape{
sLinear, // generated in a sphere, flying in direction
sSpherical, // generated in a sphere, flying away from center
sConical, // generated in a cone at angle from direction
};
bool relative;
bool relativeDirection;
bool fixed;
Shape shape;
float angle;
float sizeNoEnergy;
float gravity;
float rotation;
const Model *unitModel;
string meshName;
bool isVisibleAtNight;
bool isVisibleAtDay;
bool isDaylightAffected;
bool radiusBasedStartenergy;
int staticParticleCount;
int delay;
int lifetime;
float emissionRateFade;
GameParticleSystem* parent;
public:
UnitParticleSystem(int particleCount= 2000);
~UnitParticleSystem();
virtual ParticleSystemType getParticleSystemType() const { return pst_UnitParticleSystem;}
ParticleSystemTypeInterface * getParticleType() const {
return particleSystemType;
}
void setParticleType(ParticleSystemTypeInterface *type) {
particleSystemType = type;
}
//virtual
virtual void initParticle(Particle *p, int particleIndex);
virtual void updateParticle(Particle *p);
virtual void update();
virtual bool getVisible() const;
virtual void fade();
virtual void render(ParticleRenderer *pr, ModelRenderer *mr);
virtual void setStartTime(float startTime) { this->startTime = startTime; }
virtual float getStartTime() const { return this->startTime; }
virtual void setEndTime(float endTime) { this->endTime = endTime; }
virtual float getEndTime() const { return this->endTime; }
//set params
void setRadius(float radius) {this->radius= radius;}
void setMinRadius(float minRadius) {this->minRadius= minRadius;}
void setEmissionRateFade(float emissionRateFade) {this->emissionRateFade= emissionRateFade;}
void setWind(float windAngle, float windSpeed);
void setDirection(Vec3f direction) {this->direction= direction;}
void setSizeNoEnergy(float sizeNoEnergy) {this->sizeNoEnergy= sizeNoEnergy;}
void setGravity(float gravity) {this->gravity= gravity;}
void setRotation(float rotation);
const void setUnitModel(const Model* unitModel) {this->unitModel= unitModel;}
void setMeshName(string meshName) {this->meshName= meshName;}
void setRelative(bool relative) {this->relative= relative;}
void setRelativeDirection(bool relativeDirection) {this->relativeDirection= relativeDirection;}
void setFixed(bool fixed) {this->fixed= fixed;}
void setPrimitive(Primitive primitive) {this->primitive= primitive;}
void setStaticParticleCount(int staticParticleCount){this->staticParticleCount= staticParticleCount;}
void setIsVisibleAtNight(bool value) {this->isVisibleAtNight= value;}
void setIsDaylightAffected(bool value) {this->isDaylightAffected= value;}
void setIsVisibleAtDay(bool value) {this->isVisibleAtDay= value;}
void setRadiusBasedStartenergy(bool value) {this->radiusBasedStartenergy= value;}
void setShape(Shape shape) {this->shape= shape;}
void setAngle(float angle) {this->angle= angle;}
void setDelay(int delay) {this->delay= delay;}
void setLifetime(int lifetime) {this->lifetime= lifetime;}
void setParent(GameParticleSystem* parent) {this->parent= parent;}
GameParticleSystem* getParent() const {return parent;}
void setParentDirection(Vec3f parentDirection);
static Shape strToShape(const string& str);
virtual void saveGame(XmlNode *rootNode);
virtual void loadGame(const XmlNode *rootNode);
virtual string toString() const;
virtual Checksum getCRC();
};
// =====================================================
// class RainParticleSystem
// =====================================================
class RainParticleSystem: public ParticleSystem{
private:
Vec3f windSpeed;
float radius;
public:
RainParticleSystem(int particleCount= 4000);
virtual ParticleSystemType getParticleSystemType() const { return pst_RainParticleSystem;}
virtual void render(ParticleRenderer *pr, ModelRenderer *mr);
virtual void initParticle(Particle *p, int particleIndex);
virtual bool deathTest(Particle *p);
void setRadius(float radius);
void setWind(float windAngle, float windSpeed);
virtual string toString() const;
virtual Checksum getCRC();
};
// =====================================================
// class SnowParticleSystem
// =====================================================
class SnowParticleSystem: public ParticleSystem{
private:
Vec3f windSpeed;
float radius;
public:
SnowParticleSystem(int particleCount= 4000);
virtual ParticleSystemType getParticleSystemType() const { return pst_SnowParticleSystem;}
virtual void initParticle(Particle *p, int particleIndex);
virtual bool deathTest(Particle *p);
void setRadius(float radius);
void setWind(float windAngle, float windSpeed);
virtual string toString() const;
virtual Checksum getCRC();
};
// ===========================================================================
// AttackParticleSystem
//
/// Base class for Projectiles and Splashes
// ===========================================================================
class AttackParticleSystem: public GameParticleSystem {
protected:
float sizeNoEnergy;
float gravity;
public:
AttackParticleSystem(int particleCount);
virtual ParticleSystemType getParticleSystemType() const { return pst_ProjectileParticleSystem;}
void setSizeNoEnergy(float sizeNoEnergy) {this->sizeNoEnergy= sizeNoEnergy;}
void setGravity(float gravity) {this->gravity= gravity;}
virtual void initParticleSystem() {} // opportunity to do any initialization when the system has been created and all settings set
virtual void saveGame(XmlNode *rootNode);
virtual void loadGame(const XmlNode *rootNode);
virtual string toString() const;
virtual Checksum getCRC();
};
// =====================================================
// class ProjectileParticleSystem
// =====================================================
class ProjectileParticleSystem: public AttackParticleSystem{
public:
friend class SplashParticleSystem;
enum Trajectory{
tLinear,
tParabolic,
tSpiral
};
private:
SplashParticleSystem *nextParticleSystem;
Vec3f lastPos;
Vec3f startPos;
Vec3f endPos;
Vec3f flatPos;
Vec3f xVector;
Vec3f yVector;
Vec3f zVector;
Trajectory trajectory;
float trajectorySpeed;
//parabolic
float trajectoryScale;
float trajectoryFrequency;
float arriveDestinationDistance;
void rotateChildren();
public:
ProjectileParticleSystem(int particleCount= 1000);
virtual ~ProjectileParticleSystem();
virtual ParticleSystemType getParticleSystemType() const { return pst_SplashParticleSystem;}
void link(SplashParticleSystem *particleSystem);
virtual void update();
virtual void initParticle(Particle *p, int particleIndex);
virtual void updateParticle(Particle *p);
void setTrajectory(Trajectory trajectory) {this->trajectory= trajectory;}
void setTrajectorySpeed(float trajectorySpeed) {this->trajectorySpeed= trajectorySpeed;}
void setTrajectoryScale(float trajectoryScale) {this->trajectoryScale= trajectoryScale;}
void setTrajectoryFrequency(float trajectoryFrequency) {this->trajectoryFrequency= trajectoryFrequency;}
void setPath(Vec3f startPos, Vec3f endPos);
static Trajectory strToTrajectory(const string &str);
virtual void saveGame(XmlNode *rootNode);
virtual void loadGame(const XmlNode *rootNode);
virtual string toString() const;
virtual Checksum getCRC();
};
// =====================================================
// class SplashParticleSystem
// =====================================================
class SplashParticleSystem: public AttackParticleSystem{
public:
friend class ProjectileParticleSystem;
private:
ProjectileParticleSystem *prevParticleSystem;
float emissionRateFade;
float verticalSpreadA;
float verticalSpreadB;
float horizontalSpreadA;
float horizontalSpreadB;
float startEmissionRate;
public:
SplashParticleSystem(int particleCount= 1000);
virtual ~SplashParticleSystem();
virtual void update();
virtual void initParticle(Particle *p, int particleIndex);
virtual void updateParticle(Particle *p);
virtual void initParticleSystem();
void setEmissionRateFade(float emissionRateFade) {this->emissionRateFade= emissionRateFade;}
void setVerticalSpreadA(float verticalSpreadA) {this->verticalSpreadA= verticalSpreadA;}
void setVerticalSpreadB(float verticalSpreadB) {this->verticalSpreadB= verticalSpreadB;}
void setHorizontalSpreadA(float horizontalSpreadA) {this->horizontalSpreadA= horizontalSpreadA;}
void setHorizontalSpreadB(float horizontalSpreadB) {this->horizontalSpreadB= horizontalSpreadB;}
virtual void saveGame(XmlNode *rootNode);
virtual void loadGame(const XmlNode *rootNode);
virtual string toString() const;
virtual Checksum getCRC();
};
// =====================================================
// class ParticleManager
// =====================================================
class ParticleManager {
private:
vector<ParticleSystem *> particleSystems;
public:
ParticleManager();
~ParticleManager();
void update(int renderFps=-1);
void render(ParticleRenderer *pr, ModelRenderer *mr) const;
void manage(ParticleSystem *ps);
void end();
void cleanupParticleSystems(ParticleSystem *ps);
void cleanupParticleSystems(vector<ParticleSystem *> &particleSystems);
void cleanupUnitParticleSystems(vector<UnitParticleSystem *> &particleSystems);
int findParticleSystems(ParticleSystem *psFind, const vector<ParticleSystem *> &particleSystems) const;
bool validateParticleSystemStillExists(ParticleSystem * particleSystem) const;
void removeParticleSystemsForParticleOwner(ParticleOwner * particleOwner);
bool hasActiveParticleSystem(ParticleSystem::ParticleSystemType type) const;
};
}}//end namespace
#endif