// ============================================================== // 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; Vec3f meshPos; 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); void setMeshPos(Vec3f meshPos) { this->meshPos = meshPos; } string getMeshName() { return meshName; } 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