// ============================================================== // 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 #include #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 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 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 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 &particleSystems); void cleanupUnitParticleSystems(vector &particleSystems); int findParticleSystems(ParticleSystem *psFind, const vector &particleSystems) const; bool validateParticleSystemStillExists(ParticleSystem * particleSystem) const; void removeParticleSystemsForParticleOwner(ParticleOwner * particleOwner); bool hasActiveParticleSystem(ParticleSystem::ParticleSystemType type) const; }; }}//end namespace #endif