2010-03-27 04:09:11 +01:00
|
|
|
// ==============================================================
|
|
|
|
// This file is part of Glest Shared Library (www.glest.org)
|
|
|
|
//
|
2011-12-14 08:40:48 +01:00
|
|
|
// Copyright (C) 2001-2008 Martiño Figueroa
|
2010-03-27 04:09:11 +01:00
|
|
|
//
|
|
|
|
// 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
|
|
|
|
// ==============================================================
|
|
|
|
|
2010-05-01 22:14:25 +02:00
|
|
|
#include "math_wrapper.h"
|
2010-03-27 04:09:11 +01:00
|
|
|
#include "particle.h"
|
|
|
|
|
2010-08-24 03:21:34 +02:00
|
|
|
#include <stdexcept>
|
2010-03-27 04:09:11 +01:00
|
|
|
#include <cassert>
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
#include "util.h"
|
|
|
|
#include "particle_renderer.h"
|
|
|
|
#include "math_util.h"
|
2010-08-24 03:21:34 +02:00
|
|
|
#include "platform_common.h"
|
2012-03-10 04:27:25 +01:00
|
|
|
#include "conversion.h"
|
2012-03-13 22:58:31 +01:00
|
|
|
#include "model.h"
|
2010-03-27 04:09:11 +01:00
|
|
|
#include "leak_dumper.h"
|
|
|
|
|
2010-08-24 03:21:34 +02:00
|
|
|
using namespace std;
|
2010-03-27 04:09:11 +01:00
|
|
|
using namespace Shared::Util;
|
2010-08-24 03:21:34 +02:00
|
|
|
using namespace Shared::PlatformCommon;
|
2010-03-27 04:09:11 +01:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
namespace Shared {
|
|
|
|
namespace Graphics {
|
2010-03-27 04:09:11 +01:00
|
|
|
|
|
|
|
// =====================================================
|
|
|
|
// class ParticleSystem
|
|
|
|
// =====================================================
|
|
|
|
|
2011-07-06 07:16:25 +02:00
|
|
|
const bool checkMemory = false;
|
|
|
|
static map<void *,int> memoryObjectList;
|
|
|
|
|
2012-03-10 04:27:25 +01:00
|
|
|
void Particle::saveGame(XmlNode *rootNode) {
|
|
|
|
std::map<string,string> mapTagReplacements;
|
|
|
|
XmlNode *particleNode = rootNode->addChild("Particle");
|
|
|
|
|
|
|
|
// Vec3f pos;
|
|
|
|
particleNode->addAttribute("pos",pos.getString(), mapTagReplacements);
|
|
|
|
// Vec3f lastPos;
|
|
|
|
particleNode->addAttribute("lastPos",lastPos.getString(), mapTagReplacements);
|
|
|
|
// Vec3f speed;
|
|
|
|
particleNode->addAttribute("speed",speed.getString(), mapTagReplacements);
|
|
|
|
// Vec3f accel;
|
|
|
|
particleNode->addAttribute("accel",accel.getString(), mapTagReplacements);
|
|
|
|
// Vec4f color;
|
|
|
|
particleNode->addAttribute("color",color.getString(), mapTagReplacements);
|
|
|
|
// float size;
|
|
|
|
particleNode->addAttribute("size",floatToStr(size), mapTagReplacements);
|
|
|
|
// int energy;
|
|
|
|
particleNode->addAttribute("energy",intToStr(energy), mapTagReplacements);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2012-03-13 22:58:31 +01:00
|
|
|
void Particle::loadGame(const XmlNode *rootNode) {
|
|
|
|
const XmlNode *particleNode = rootNode;
|
|
|
|
|
|
|
|
//particleNode = aiNode->getAttribute("startLoc")->getIntValue();
|
|
|
|
// Vec3f pos;
|
|
|
|
pos = Vec3f::strToVec3(particleNode->getAttribute("pos")->getValue());
|
|
|
|
// Vec3f lastPos;
|
|
|
|
lastPos = Vec3f::strToVec3(particleNode->getAttribute("lastPos")->getValue());
|
|
|
|
// Vec3f speed;
|
|
|
|
speed = Vec3f::strToVec3(particleNode->getAttribute("speed")->getValue());
|
|
|
|
// Vec3f accel;
|
|
|
|
accel = Vec3f::strToVec3(particleNode->getAttribute("accel")->getValue());
|
|
|
|
// Vec4f color;
|
|
|
|
color = Vec4f::strToVec4(particleNode->getAttribute("color")->getValue());
|
|
|
|
// float size;
|
|
|
|
size = particleNode->getAttribute("size")->getFloatValue();
|
|
|
|
// int energy;
|
|
|
|
energy = particleNode->getAttribute("energy")->getIntValue();
|
|
|
|
}
|
|
|
|
|
2011-06-25 22:44:46 +02:00
|
|
|
ParticleSystem::ParticleSystem(int particleCount) {
|
2011-07-06 07:16:25 +02:00
|
|
|
if(checkMemory) {
|
|
|
|
printf("++ Create ParticleSystem [%p]\n",this);
|
|
|
|
memoryObjectList[this]++;
|
|
|
|
}
|
2011-06-25 22:44:46 +02:00
|
|
|
|
2011-12-02 23:04:02 +01:00
|
|
|
//assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false);
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
//init particle vector
|
2011-03-14 00:16:07 +01:00
|
|
|
blendMode= bmOne;
|
2010-08-24 03:21:34 +02:00
|
|
|
//particles= new Particle[particleCount];
|
|
|
|
particles.clear();
|
2010-08-26 03:25:27 +02:00
|
|
|
//particles.reserve(particleCount);
|
|
|
|
particles.resize(particleCount);
|
2010-08-24 03:21:34 +02:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
state= sPlay;
|
2011-03-14 00:16:07 +01:00
|
|
|
aliveParticleCount= 0;
|
2010-03-27 04:09:11 +01:00
|
|
|
active= true;
|
|
|
|
visible= true;
|
|
|
|
|
|
|
|
//vars
|
|
|
|
texture= NULL;
|
|
|
|
particleObserver= NULL;
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
//params
|
2010-10-06 19:04:51 +02:00
|
|
|
this->particleCount= particleCount;
|
2010-08-24 03:21:34 +02:00
|
|
|
//this->particleCount= particles.size();
|
2010-03-27 04:09:11 +01:00
|
|
|
maxParticleEnergy= 250;
|
|
|
|
varParticleEnergy= 50;
|
|
|
|
pos= Vec3f(0.0f);
|
|
|
|
color= Vec4f(1.0f);
|
|
|
|
colorNoEnergy= Vec4f(0.0f);
|
2010-09-24 18:36:59 +02:00
|
|
|
emissionRate= 15.0f;
|
2010-09-25 16:38:00 +02:00
|
|
|
emissionState= 1.0f; // initialized with 1 because we must have at least one particle in the beginning!
|
2010-03-27 04:09:11 +01:00
|
|
|
speed= 1.0f;
|
2011-03-14 00:16:07 +01:00
|
|
|
teamcolorNoEnergy= false;
|
|
|
|
teamcolorEnergy= false;
|
|
|
|
alternations= 0;
|
2012-01-07 21:24:54 +01:00
|
|
|
particleSystemStartDelay= 0;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ParticleSystem::~ParticleSystem(){
|
2011-07-06 07:16:25 +02:00
|
|
|
if(checkMemory) {
|
|
|
|
printf("-- Delete ParticleSystem [%p]\n",this);
|
|
|
|
memoryObjectList[this]--;
|
|
|
|
assert(memoryObjectList[this] == 0);
|
|
|
|
}
|
2011-06-25 22:44:46 +02:00
|
|
|
|
2010-08-24 03:21:34 +02:00
|
|
|
//delete [] particles;
|
|
|
|
particles.clear();
|
2011-09-28 08:57:42 +02:00
|
|
|
|
|
|
|
delete particleObserver;
|
|
|
|
particleObserver = NULL;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// =============== VIRTUAL ======================
|
|
|
|
|
|
|
|
//updates all living particles and creates new ones
|
2011-03-14 00:16:07 +01:00
|
|
|
void ParticleSystem::update(){
|
|
|
|
if(aliveParticleCount > (int) particles.size()){
|
2010-08-24 03:21:34 +02:00
|
|
|
throw runtime_error("aliveParticleCount >= particles.size()");
|
|
|
|
}
|
2012-01-07 21:24:54 +01:00
|
|
|
if(particleSystemStartDelay>0){
|
|
|
|
particleSystemStartDelay--;
|
|
|
|
}
|
|
|
|
else if(state != sPause){
|
2011-03-14 00:16:07 +01:00
|
|
|
for(int i= 0; i < aliveParticleCount; ++i){
|
2010-03-27 04:09:11 +01:00
|
|
|
updateParticle(&particles[i]);
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
if(deathTest(&particles[i])){
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
//kill the particle
|
|
|
|
killParticle(&particles[i]);
|
|
|
|
|
2010-08-24 03:21:34 +02:00
|
|
|
//maintain alive particles at front of the array
|
2011-03-14 00:16:07 +01:00
|
|
|
if(aliveParticleCount > 0){
|
|
|
|
particles[i]= particles[aliveParticleCount];
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-26 21:01:44 +02:00
|
|
|
if(state != ParticleSystem::sFade){
|
2011-03-14 00:16:07 +01:00
|
|
|
emissionState= emissionState + emissionRate;
|
|
|
|
int emissionIntValue= (int) emissionState;
|
|
|
|
for(int i= 0; i < emissionIntValue; i++){
|
|
|
|
Particle *p= createParticle();
|
2010-03-27 04:09:11 +01:00
|
|
|
initParticle(p, i);
|
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
emissionState= emissionState - (float) emissionIntValue;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
|
|
|
|
if(active){
|
|
|
|
pr->renderSystem(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ParticleSystem::BlendMode ParticleSystem::strToBlendMode(const string &str){
|
2011-03-14 00:16:07 +01:00
|
|
|
if(str == "normal"){
|
2010-03-27 04:09:11 +01:00
|
|
|
return bmOne;
|
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
else if(str == "black"){
|
2010-03-27 04:09:11 +01:00
|
|
|
return bmOneMinusAlpha;
|
|
|
|
}
|
|
|
|
else{
|
2011-07-07 00:23:51 +02:00
|
|
|
throw runtime_error("Unknown particle mode: " + str);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// =============== SET ==========================
|
|
|
|
|
|
|
|
void ParticleSystem::setState(State state){
|
|
|
|
this->state= state;
|
2011-07-07 00:23:51 +02:00
|
|
|
for(int i=getChildCount()-1; i>=0; i--)
|
|
|
|
getChild(i)->setState(state);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::setTexture(Texture *texture){
|
|
|
|
this->texture= texture;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::setPos(Vec3f pos){
|
|
|
|
this->pos= pos;
|
2011-07-07 00:23:51 +02:00
|
|
|
for(int i=getChildCount()-1; i>=0; i--)
|
|
|
|
getChild(i)->setPos(pos);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::setColor(Vec4f color){
|
|
|
|
this->color= color;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::setColorNoEnergy(Vec4f colorNoEnergy){
|
|
|
|
this->colorNoEnergy= colorNoEnergy;
|
|
|
|
}
|
|
|
|
|
2010-09-24 18:36:59 +02:00
|
|
|
void ParticleSystem::setEmissionRate(float emissionRate){
|
2010-03-27 04:09:11 +01:00
|
|
|
this->emissionRate= emissionRate;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::setMaxParticleEnergy(int maxParticleEnergy){
|
2011-03-14 00:16:07 +01:00
|
|
|
this->maxParticleEnergy= maxParticleEnergy;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::setVarParticleEnergy(int varParticleEnergy){
|
|
|
|
this->varParticleEnergy= varParticleEnergy;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::setParticleSize(float particleSize){
|
|
|
|
this->particleSize= particleSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::setSpeed(float speed){
|
|
|
|
this->speed= speed;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::setActive(bool active){
|
|
|
|
this->active= active;
|
2011-07-07 00:23:51 +02:00
|
|
|
for(int i=getChildCount()-1; i>=0; i--)
|
|
|
|
getChild(i)->setActive(active);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::setObserver(ParticleObserver *particleObserver){
|
|
|
|
this->particleObserver= particleObserver;
|
|
|
|
}
|
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
ParticleSystem* ParticleSystem::getChild(int i){
|
|
|
|
throw std::out_of_range("ParticleSystem::getChild bad");
|
|
|
|
}
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
void ParticleSystem::setVisible(bool visible){
|
|
|
|
this->visible= visible;
|
2011-07-07 00:23:51 +02:00
|
|
|
for(int i=getChildCount()-1; i>=0; i--)
|
|
|
|
getChild(i)->setVisible(visible);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
2012-03-10 04:27:25 +01:00
|
|
|
void ParticleSystem::saveGame(XmlNode *rootNode) {
|
|
|
|
std::map<string,string> mapTagReplacements;
|
|
|
|
XmlNode *particleSystemNode = rootNode->addChild("ParticleSystem");
|
|
|
|
|
|
|
|
// std::vector<Particle> particles;
|
|
|
|
for(unsigned int i = 0; i < particles.size(); ++i) {
|
|
|
|
Particle &particle = particles[i];
|
|
|
|
particle.saveGame(particleSystemNode);
|
|
|
|
}
|
|
|
|
// RandomGen random;
|
|
|
|
particleSystemNode->addAttribute("random",intToStr(random.getLastNumber()), mapTagReplacements);
|
|
|
|
|
|
|
|
// BlendMode blendMode;
|
|
|
|
particleSystemNode->addAttribute("blendMode",intToStr(blendMode), mapTagReplacements);
|
|
|
|
// State state;
|
|
|
|
particleSystemNode->addAttribute("state",intToStr(state), mapTagReplacements);
|
|
|
|
// bool active;
|
|
|
|
particleSystemNode->addAttribute("active",intToStr(active), mapTagReplacements);
|
|
|
|
// bool visible;
|
|
|
|
particleSystemNode->addAttribute("visible",intToStr(visible), mapTagReplacements);
|
|
|
|
// int aliveParticleCount;
|
|
|
|
particleSystemNode->addAttribute("aliveParticleCount",intToStr(aliveParticleCount), mapTagReplacements);
|
|
|
|
// int particleCount;
|
|
|
|
particleSystemNode->addAttribute("particleCount",intToStr(particleCount), mapTagReplacements);
|
|
|
|
//
|
|
|
|
// Texture *texture;
|
|
|
|
// Vec3f pos;
|
|
|
|
particleSystemNode->addAttribute("pos",pos.getString(), mapTagReplacements);
|
|
|
|
// Vec4f color;
|
|
|
|
particleSystemNode->addAttribute("color",color.getString(), mapTagReplacements);
|
|
|
|
// Vec4f colorNoEnergy;
|
|
|
|
particleSystemNode->addAttribute("colorNoEnergy",colorNoEnergy.getString(), mapTagReplacements);
|
|
|
|
// float emissionRate;
|
|
|
|
particleSystemNode->addAttribute("emissionRate",floatToStr(emissionRate), mapTagReplacements);
|
|
|
|
// float emissionState;
|
|
|
|
particleSystemNode->addAttribute("emissionState",floatToStr(emissionState), mapTagReplacements);
|
|
|
|
// int maxParticleEnergy;
|
|
|
|
particleSystemNode->addAttribute("maxParticleEnergy",intToStr(maxParticleEnergy), mapTagReplacements);
|
|
|
|
// int varParticleEnergy;
|
|
|
|
particleSystemNode->addAttribute("varParticleEnergy",intToStr(varParticleEnergy), mapTagReplacements);
|
|
|
|
// float particleSize;
|
|
|
|
particleSystemNode->addAttribute("particleSize",floatToStr(particleSize), mapTagReplacements);
|
|
|
|
// float speed;
|
|
|
|
particleSystemNode->addAttribute("speed",floatToStr(speed), mapTagReplacements);
|
|
|
|
// Vec3f factionColor;
|
|
|
|
particleSystemNode->addAttribute("factionColor",factionColor.getString(), mapTagReplacements);
|
|
|
|
// bool teamcolorNoEnergy;
|
|
|
|
particleSystemNode->addAttribute("teamcolorNoEnergy",intToStr(teamcolorNoEnergy), mapTagReplacements);
|
|
|
|
// bool teamcolorEnergy;
|
|
|
|
particleSystemNode->addAttribute("teamcolorEnergy",intToStr(teamcolorEnergy), mapTagReplacements);
|
|
|
|
// int alternations;
|
|
|
|
particleSystemNode->addAttribute("alternations",intToStr(alternations), mapTagReplacements);
|
|
|
|
// int particleSystemStartDelay;
|
|
|
|
particleSystemNode->addAttribute("particleSystemStartDelay",intToStr(particleSystemStartDelay), mapTagReplacements);
|
|
|
|
// ParticleObserver *particleObserver;
|
|
|
|
if(particleObserver != NULL) {
|
|
|
|
particleObserver->saveGame(particleSystemNode);
|
|
|
|
}
|
|
|
|
}
|
2012-03-13 22:58:31 +01:00
|
|
|
|
|
|
|
void ParticleSystem::loadGame(const XmlNode *rootNode) {
|
|
|
|
const XmlNode *particleSystemNode = rootNode->getChild("ParticleSystem");
|
|
|
|
|
|
|
|
// std::vector<Particle> particles;
|
|
|
|
// for(unsigned int i = 0; i < particles.size(); ++i) {
|
|
|
|
// Particle &particle = particles[i];
|
|
|
|
// particle.saveGame(particleSystemNode);
|
|
|
|
// }
|
|
|
|
vector<XmlNode *> particleNodeList = particleSystemNode->getChildList("Particle");
|
|
|
|
for(unsigned int i = 0; i < particleNodeList.size(); ++i) {
|
|
|
|
XmlNode *node = particleNodeList[i];
|
|
|
|
|
|
|
|
Particle particle;
|
|
|
|
particle.loadGame(node);
|
|
|
|
particles.push_back(particle);
|
|
|
|
}
|
|
|
|
|
|
|
|
// RandomGen random;
|
|
|
|
random.setLastNumber(particleSystemNode->getAttribute("random")->getIntValue());
|
|
|
|
|
|
|
|
// BlendMode blendMode;
|
|
|
|
blendMode = static_cast<BlendMode>(particleSystemNode->getAttribute("blendMode")->getIntValue());
|
|
|
|
// State state;
|
|
|
|
state = static_cast<State>(particleSystemNode->getAttribute("state")->getIntValue());
|
|
|
|
// bool active;
|
|
|
|
active = particleSystemNode->getAttribute("active")->getIntValue();
|
|
|
|
// bool visible;
|
|
|
|
visible = particleSystemNode->getAttribute("visible")->getIntValue();
|
|
|
|
// int aliveParticleCount;
|
|
|
|
aliveParticleCount = particleSystemNode->getAttribute("aliveParticleCount")->getIntValue();
|
|
|
|
// int particleCount;
|
|
|
|
particleCount = particleSystemNode->getAttribute("particleCount")->getIntValue();
|
|
|
|
//
|
|
|
|
// Texture *texture;
|
|
|
|
// Vec3f pos;
|
|
|
|
pos = Vec3f::strToVec3(particleSystemNode->getAttribute("pos")->getValue());
|
|
|
|
// Vec4f color;
|
|
|
|
color = Vec4f::strToVec4(particleSystemNode->getAttribute("color")->getValue());
|
|
|
|
// Vec4f colorNoEnergy;
|
|
|
|
colorNoEnergy = Vec4f::strToVec4(particleSystemNode->getAttribute("colorNoEnergy")->getValue());
|
|
|
|
// float emissionRate;
|
|
|
|
emissionRate = particleSystemNode->getAttribute("emissionRate")->getFloatValue();
|
|
|
|
// float emissionState;
|
|
|
|
emissionState = particleSystemNode->getAttribute("emissionState")->getFloatValue();
|
|
|
|
// int maxParticleEnergy;
|
|
|
|
maxParticleEnergy = particleSystemNode->getAttribute("maxParticleEnergy")->getIntValue();
|
|
|
|
// int varParticleEnergy;
|
|
|
|
varParticleEnergy = particleSystemNode->getAttribute("varParticleEnergy")->getIntValue();
|
|
|
|
// float particleSize;
|
|
|
|
particleSize = particleSystemNode->getAttribute("particleSize")->getFloatValue();
|
|
|
|
// float speed;
|
|
|
|
speed = particleSystemNode->getAttribute("speed")->getFloatValue();
|
|
|
|
// Vec3f factionColor;
|
|
|
|
factionColor = Vec3f::strToVec3(particleSystemNode->getAttribute("factionColor")->getValue());
|
|
|
|
// bool teamcolorNoEnergy;
|
|
|
|
teamcolorNoEnergy = particleSystemNode->getAttribute("teamcolorNoEnergy")->getIntValue();
|
|
|
|
// bool teamcolorEnergy;
|
|
|
|
teamcolorEnergy = particleSystemNode->getAttribute("teamcolorEnergy")->getIntValue();
|
|
|
|
// int alternations;
|
|
|
|
alternations = particleSystemNode->getAttribute("alternations")->getIntValue();
|
|
|
|
// int particleSystemStartDelay;
|
|
|
|
particleSystemStartDelay = particleSystemNode->getAttribute("particleSystemStartDelay")->getIntValue();
|
|
|
|
// ParticleObserver *particleObserver;
|
|
|
|
//if(particleObserver != NULL) {
|
|
|
|
// particleObserver->loadGame(particleSystemNode);
|
|
|
|
//}
|
|
|
|
}
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
// =============== MISC =========================
|
2011-03-14 00:16:07 +01:00
|
|
|
void ParticleSystem::fade(){
|
|
|
|
if(particleObserver != NULL){
|
2011-06-25 22:44:46 +02:00
|
|
|
if(state != sPlay) {
|
|
|
|
char szBuf[4096]="";
|
|
|
|
sprintf(szBuf,"state != sPlay, state = [%d]",state);
|
|
|
|
//throw runtime_error(szBuf);
|
|
|
|
//printf(szBuf);
|
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"%s",szBuf);
|
|
|
|
}
|
2010-11-09 10:06:52 +01:00
|
|
|
assert(state == sPlay);
|
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
state= sFade;
|
2011-03-14 00:16:07 +01:00
|
|
|
if(particleObserver != NULL){
|
2010-03-27 04:09:11 +01:00
|
|
|
particleObserver->update(this);
|
|
|
|
}
|
2011-07-07 00:23:51 +02:00
|
|
|
for(int i=getChildCount()-1; i>=0; i--)
|
|
|
|
getChild(i)->fade();
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int ParticleSystem::isEmpty() const{
|
|
|
|
assert(aliveParticleCount>=0);
|
2011-03-14 00:16:07 +01:00
|
|
|
return aliveParticleCount == 0 && state != sPause;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// =============== PROTECTED =========================
|
|
|
|
|
|
|
|
// if there is one dead particle it returns it else, return the particle with
|
|
|
|
// less energy
|
|
|
|
Particle * ParticleSystem::createParticle(){
|
|
|
|
|
|
|
|
//if any dead particles
|
2011-03-14 00:16:07 +01:00
|
|
|
if(aliveParticleCount < particleCount){
|
2010-03-27 04:09:11 +01:00
|
|
|
++aliveParticleCount;
|
2011-03-14 00:16:07 +01:00
|
|
|
return &particles[aliveParticleCount - 1];
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
//if not
|
2011-03-14 00:16:07 +01:00
|
|
|
int minEnergy= particles[0].energy;
|
|
|
|
int minEnergyParticle= 0;
|
2010-10-06 19:04:51 +02:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
for(int i= 0; i < particleCount; ++i){
|
2010-10-06 19:04:51 +02:00
|
|
|
if(particles[i].energy < minEnergy){
|
2011-03-14 00:16:07 +01:00
|
|
|
minEnergy= particles[i].energy;
|
|
|
|
minEnergyParticle= i;
|
2010-10-06 19:04:51 +02:00
|
|
|
}
|
|
|
|
}
|
2010-08-24 03:21:34 +02:00
|
|
|
return &particles[minEnergyParticle];
|
2010-03-27 04:09:11 +01:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
/*
|
|
|
|
//if any dead particles
|
|
|
|
if(aliveParticleCount < particleCount) {
|
|
|
|
++aliveParticleCount;
|
|
|
|
return &particles[aliveParticleCount-1];
|
|
|
|
}
|
2010-08-24 03:21:34 +02:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
//if not
|
|
|
|
int minEnergy = particles[0].energy;
|
|
|
|
int minEnergyParticle = 0;
|
2010-08-24 03:21:34 +02:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
for(int i = 0; i < particleCount; ++i){
|
|
|
|
if(particles[i].energy < minEnergy){
|
|
|
|
minEnergy = particles[i].energy;
|
|
|
|
minEnergyParticle = i;
|
|
|
|
}
|
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
return &particles[minEnergyParticle];
|
|
|
|
*/
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::initParticle(Particle *p, int particleIndex){
|
|
|
|
p->pos= pos;
|
|
|
|
p->lastPos= p->pos;
|
|
|
|
p->speed= Vec3f(0.0f);
|
|
|
|
p->accel= Vec3f(0.0f);
|
|
|
|
p->color= Vec4f(1.0f, 1.0f, 1.0f, 1.0);
|
|
|
|
p->size= particleSize;
|
|
|
|
p->energy= maxParticleEnergy + random.randRange(-varParticleEnergy, varParticleEnergy);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::updateParticle(Particle *p){
|
|
|
|
p->lastPos= p->pos;
|
|
|
|
p->pos= p->pos + p->speed;
|
|
|
|
p->speed= p->speed + p->accel;
|
|
|
|
p->energy--;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ParticleSystem::deathTest(Particle *p){
|
|
|
|
return p->energy <= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::killParticle(Particle *p){
|
|
|
|
aliveParticleCount--;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleSystem::setFactionColor(Vec3f factionColor){
|
2011-03-14 00:16:07 +01:00
|
|
|
this->factionColor= factionColor;
|
2010-03-27 04:09:11 +01:00
|
|
|
Vec3f tmpCol;
|
2011-03-14 00:16:07 +01:00
|
|
|
|
|
|
|
if(teamcolorEnergy){
|
|
|
|
this->color= Vec4f(factionColor.x, factionColor.y, factionColor.z, this->color.w);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
if(teamcolorNoEnergy){
|
|
|
|
this->colorNoEnergy= Vec4f(factionColor.x, factionColor.y, factionColor.z, this->colorNoEnergy.w);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
2011-07-07 00:23:51 +02:00
|
|
|
for(int i=getChildCount()-1; i>=0; i--)
|
|
|
|
getChild(i)->setFactionColor(factionColor);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
|
|
// FireParticleSystem
|
|
|
|
// ===========================================================================
|
|
|
|
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
FireParticleSystem::FireParticleSystem(int particleCount) :
|
|
|
|
ParticleSystem(particleCount){
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
radius= 0.5f;
|
|
|
|
speed= 0.01f;
|
|
|
|
windSpeed= Vec3f(0.0f);
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
setParticleSize(0.6f);
|
|
|
|
setColorNoEnergy(Vec4f(1.0f, 0.5f, 0.0f, 1.0f));
|
|
|
|
}
|
|
|
|
|
|
|
|
void FireParticleSystem::initParticle(Particle *p, int particleIndex){
|
|
|
|
ParticleSystem::initParticle(p, particleIndex);
|
2011-03-14 00:16:07 +01:00
|
|
|
|
|
|
|
float ang= random.randRange(-2.0f * pi, 2.0f * pi);
|
2010-05-01 22:14:25 +02:00
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
float mod= streflop::fabsf(static_cast<streflop::Simple>(random.randRange(-radius, radius)));
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2012-02-10 07:21:06 +01:00
|
|
|
float x= streflop::sinf(static_cast<streflop::Simple>(ang))*mod;
|
|
|
|
float y= streflop::cosf(static_cast<streflop::Simple>(ang))*mod;
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2012-02-10 07:21:06 +01:00
|
|
|
float radRatio= streflop::sqrtf(static_cast<streflop::Simple>(mod/radius));
|
2010-05-01 22:14:25 +02:00
|
|
|
#else
|
|
|
|
float mod= fabsf(random.randRange(-radius, radius));
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
float x= sinf(ang) * mod;
|
|
|
|
float y= cosf(ang) * mod;
|
2010-05-01 22:14:25 +02:00
|
|
|
|
2012-02-10 07:21:06 +01:00
|
|
|
float radRatio= sqrtf((mod / radius));
|
2010-05-01 22:14:25 +02:00
|
|
|
#endif
|
2010-03-27 04:09:11 +01:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
p->color= colorNoEnergy * 0.5f + colorNoEnergy * 0.5f * radRatio;
|
|
|
|
p->energy= static_cast<int> (maxParticleEnergy * radRatio)
|
|
|
|
+ random.randRange(-varParticleEnergy, varParticleEnergy);
|
|
|
|
p->pos= Vec3f(pos.x + x, pos.y + random.randRange(-radius / 2, radius / 2), pos.z + y);
|
2010-03-27 04:09:11 +01:00
|
|
|
p->lastPos= pos;
|
|
|
|
p->size= particleSize;
|
2011-03-14 00:16:07 +01:00
|
|
|
p->speed= Vec3f(0, speed + speed * random.randRange(-0.5f, 0.5f), 0) + windSpeed;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void FireParticleSystem::updateParticle(Particle *p){
|
|
|
|
p->lastPos= p->pos;
|
2011-03-14 00:16:07 +01:00
|
|
|
p->pos= p->pos + p->speed;
|
2010-03-27 04:09:11 +01:00
|
|
|
p->energy--;
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
if(p->color.x > 0.0f)
|
2010-03-27 04:09:11 +01:00
|
|
|
p->color.x*= 0.98f;
|
2011-03-14 00:16:07 +01:00
|
|
|
if(p->color.y > 0.0f)
|
2010-03-27 04:09:11 +01:00
|
|
|
p->color.y*= 0.98f;
|
2011-03-14 00:16:07 +01:00
|
|
|
if(p->color.w > 0.0f)
|
2010-03-27 04:09:11 +01:00
|
|
|
p->color.w*= 0.98f;
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
p->speed.x*= 1.001f;
|
2010-03-27 04:09:11 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// ================= SET PARAMS ====================
|
|
|
|
|
|
|
|
void FireParticleSystem::setRadius(float radius){
|
|
|
|
this->radius= radius;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FireParticleSystem::setWind(float windAngle, float windSpeed){
|
2010-05-01 22:14:25 +02:00
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
this->windSpeed.x= streflop::sinf(static_cast<streflop::Simple>(degToRad(windAngle)))*windSpeed;
|
2010-03-27 04:09:11 +01:00
|
|
|
this->windSpeed.y= 0.0f;
|
2012-02-10 07:21:06 +01:00
|
|
|
this->windSpeed.z= streflop::cosf(static_cast<streflop::Simple>(degToRad(windAngle)))*windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
#else
|
2011-03-14 00:16:07 +01:00
|
|
|
this->windSpeed.x= sinf(degToRad(windAngle)) * windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
this->windSpeed.y= 0.0f;
|
2011-03-14 00:16:07 +01:00
|
|
|
this->windSpeed.z= cosf(degToRad(windAngle)) * windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
#endif
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
2012-03-13 22:58:31 +01:00
|
|
|
void FireParticleSystem::saveGame(XmlNode *rootNode) {
|
|
|
|
std::map<string,string> mapTagReplacements;
|
|
|
|
XmlNode *fireParticleSystemNode = rootNode->addChild("FireParticleSystem");
|
|
|
|
|
|
|
|
ParticleSystem::saveGame(fireParticleSystemNode);
|
|
|
|
|
|
|
|
// float radius;
|
|
|
|
fireParticleSystemNode->addAttribute("radius",floatToStr(radius), mapTagReplacements);
|
|
|
|
// Vec3f windSpeed;
|
|
|
|
fireParticleSystemNode->addAttribute("windSpeed",windSpeed.getString(), mapTagReplacements);
|
|
|
|
}
|
|
|
|
void FireParticleSystem::loadGame(const XmlNode *rootNode) {
|
|
|
|
const XmlNode *fireParticleSystemNode = rootNode;
|
|
|
|
|
|
|
|
ParticleSystem::loadGame(fireParticleSystemNode);
|
|
|
|
|
|
|
|
// float radius;
|
|
|
|
radius = fireParticleSystemNode->getAttribute("radius")->getFloatValue();
|
|
|
|
// Vec3f windSpeed;
|
|
|
|
windSpeed = Vec3f::strToVec3(fireParticleSystemNode->getAttribute("windSpeed")->getValue());
|
|
|
|
}
|
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
// ===========================================================================
|
|
|
|
// GameParticleSystem
|
|
|
|
// ===========================================================================
|
|
|
|
|
|
|
|
GameParticleSystem::GameParticleSystem(int particleCount):
|
|
|
|
ParticleSystem(particleCount),
|
|
|
|
primitive(pQuad),
|
|
|
|
model(NULL),
|
|
|
|
modelCycle(0.0f),
|
|
|
|
tween(0.0f),
|
|
|
|
offset(0.0f),
|
|
|
|
direction(0.0f, 1.0f, 0.0f)
|
|
|
|
{}
|
|
|
|
|
|
|
|
GameParticleSystem::~GameParticleSystem(){
|
2011-09-01 03:11:23 +02:00
|
|
|
for(Children::iterator it= children.begin(); it != children.end(); ++it){
|
2011-07-07 00:23:51 +02:00
|
|
|
(*it)->setParent(NULL);
|
|
|
|
(*it)->fade();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GameParticleSystem::Primitive GameParticleSystem::strToPrimitive(const string &str){
|
|
|
|
if(str == "quad"){
|
|
|
|
return pQuad;
|
|
|
|
}
|
|
|
|
else if(str == "line"){
|
|
|
|
return pLine;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
throw runtime_error("Unknown particle primitive: " + str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int GameParticleSystem::getChildCount(){
|
|
|
|
return children.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
ParticleSystem* GameParticleSystem::getChild(int i){
|
|
|
|
return children.at(i); // does bounds checking
|
|
|
|
}
|
|
|
|
|
|
|
|
void GameParticleSystem::addChild(UnitParticleSystem* child) {
|
|
|
|
assert(!child->getParent());
|
|
|
|
child->setParent(this);
|
|
|
|
children.push_back(child);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GameParticleSystem::removeChild(UnitParticleSystem* child){
|
|
|
|
assert(this == child->getParent());
|
|
|
|
Children::iterator it = std::find(children.begin(),children.end(),child);
|
|
|
|
assert(it != children.end());
|
|
|
|
children.erase(it);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GameParticleSystem::setPos(Vec3f pos){
|
|
|
|
this->pos= pos;
|
|
|
|
positionChildren();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GameParticleSystem::positionChildren() {
|
|
|
|
Vec3f child_pos = pos - offset;
|
|
|
|
for(int i=getChildCount()-1; i>=0; i--)
|
|
|
|
getChild(i)->setPos(child_pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GameParticleSystem::setOffset(Vec3f offset){
|
|
|
|
this->offset= offset;
|
|
|
|
positionChildren();
|
|
|
|
}
|
|
|
|
|
|
|
|
void GameParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
|
|
|
|
if(active){
|
|
|
|
if(model != NULL){
|
|
|
|
pr->renderModel(this, mr);
|
|
|
|
}
|
|
|
|
switch(primitive){
|
|
|
|
case pQuad:
|
|
|
|
pr->renderSystem(this);
|
|
|
|
break;
|
|
|
|
case pLine:
|
|
|
|
pr->renderSystemLine(this);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GameParticleSystem::setTween(float relative,float absolute) {
|
|
|
|
if(model){
|
|
|
|
// animation?
|
|
|
|
if(modelCycle == 0.0f) {
|
|
|
|
tween= relative;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
if(streflop::fabs(static_cast<streflop::Simple>(absolute)) <= 0.00001f){
|
2011-07-07 00:23:51 +02:00
|
|
|
#else
|
|
|
|
if(fabs(absolute) <= 0.00001f){
|
|
|
|
#endif
|
|
|
|
tween = 0.0f;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
tween= streflop::fmod(static_cast<streflop::Simple>(absolute), static_cast<streflop::Simple>(modelCycle));
|
2011-07-07 00:23:51 +02:00
|
|
|
#else
|
|
|
|
tween= fmod(absolute, modelCycle);
|
|
|
|
#endif
|
|
|
|
tween /= modelCycle;
|
|
|
|
}
|
|
|
|
}
|
2011-09-10 05:57:51 +02:00
|
|
|
|
|
|
|
truncateDecimal<float>(tween);
|
2011-07-19 01:46:11 +02:00
|
|
|
if(tween < 0.0f || tween > 1.0f) {
|
2011-09-22 07:14:20 +02:00
|
|
|
//printf("In [%s::%s Line: %d] WARNING setting tween to [%f] clamping tween, modelCycle [%f] absolute [%f] relative [%f]\n",__FILE__,__FUNCTION__,__LINE__,tween,modelCycle,absolute,relative);
|
2011-08-31 18:12:02 +02:00
|
|
|
//assert(tween >= 0.0f && tween <= 1.0f);
|
2011-07-19 01:46:11 +02:00
|
|
|
}
|
2011-07-19 02:17:32 +02:00
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
tween= clamp(tween, 0.0f, 1.0f);
|
|
|
|
}
|
2011-09-01 03:11:23 +02:00
|
|
|
for(Children::iterator it= children.begin(); it != children.end(); ++it)
|
2011-07-07 00:23:51 +02:00
|
|
|
(*it)->setTween(relative,absolute);
|
|
|
|
}
|
|
|
|
|
2012-03-13 22:58:31 +01:00
|
|
|
void GameParticleSystem::saveGame(XmlNode *rootNode) {
|
|
|
|
std::map<string,string> mapTagReplacements;
|
|
|
|
XmlNode *gameParticleSystemNode = rootNode->addChild("GameParticleSystem");
|
|
|
|
|
|
|
|
ParticleSystem::saveGame(gameParticleSystemNode);
|
|
|
|
|
|
|
|
// Children children;
|
|
|
|
for(unsigned int i = 0; i < children.size(); ++i) {
|
|
|
|
children[i]->saveGame(gameParticleSystemNode);
|
|
|
|
}
|
|
|
|
// Primitive primitive;
|
|
|
|
gameParticleSystemNode->addAttribute("primitive",intToStr(primitive), mapTagReplacements);
|
|
|
|
// Model *model;
|
|
|
|
if(model != NULL) {
|
|
|
|
gameParticleSystemNode->addAttribute("model",model->getFileName(), mapTagReplacements);
|
|
|
|
}
|
|
|
|
// float modelCycle;
|
|
|
|
gameParticleSystemNode->addAttribute("modelCycle",floatToStr(modelCycle), mapTagReplacements);
|
|
|
|
// Vec3f offset;
|
|
|
|
gameParticleSystemNode->addAttribute("offset",offset.getString(), mapTagReplacements);
|
|
|
|
// Vec3f direction;
|
|
|
|
gameParticleSystemNode->addAttribute("direction",direction.getString(), mapTagReplacements);
|
|
|
|
// float tween;
|
|
|
|
gameParticleSystemNode->addAttribute("tween",floatToStr(tween), mapTagReplacements);
|
|
|
|
}
|
|
|
|
void GameParticleSystem::loadGame(const XmlNode *rootNode) {
|
|
|
|
const XmlNode *gameParticleSystemNode = rootNode;
|
|
|
|
|
|
|
|
ParticleSystem::loadGame(gameParticleSystemNode);
|
|
|
|
|
|
|
|
//radius = fireParticleSystemNode->getAttribute("radius")->getFloatValue();
|
|
|
|
|
|
|
|
// Children children;
|
|
|
|
// for(unsigned int i = 0; i < children.size(); ++i) {
|
|
|
|
// children[i]->saveGame(gameParticleSystemNode);
|
|
|
|
// }
|
|
|
|
vector<XmlNode *> childrenNodeList = gameParticleSystemNode->getChildList("UnitParticleSystem");
|
|
|
|
for(unsigned int i = 0; i < childrenNodeList.size(); ++i) {
|
|
|
|
XmlNode *node = childrenNodeList[i];
|
|
|
|
|
|
|
|
UnitParticleSystem *ups = new UnitParticleSystem();
|
|
|
|
ups->loadGame(node);
|
|
|
|
|
|
|
|
children.push_back(ups);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Primitive primitive;
|
|
|
|
primitive = static_cast<Primitive>(gameParticleSystemNode->getAttribute("primitive")->getIntValue());
|
|
|
|
// Model *model;
|
|
|
|
//if(model != NULL) {
|
|
|
|
// gameParticleSystemNode->addAttribute("model",model->getFileName(), mapTagReplacements);
|
|
|
|
//}
|
|
|
|
// float modelCycle;
|
|
|
|
//gameParticleSystemNode->addAttribute("modelCycle",floatToStr(modelCycle), mapTagReplacements);
|
|
|
|
modelCycle = gameParticleSystemNode->getAttribute("modelCycle")->getFloatValue();
|
|
|
|
// Vec3f offset;
|
|
|
|
offset = Vec3f::strToVec3(gameParticleSystemNode->getAttribute("modelCycle")->getValue());
|
|
|
|
// Vec3f direction;
|
|
|
|
direction = Vec3f::strToVec3(gameParticleSystemNode->getAttribute("direction")->getValue());
|
|
|
|
// float tween;
|
|
|
|
tween = gameParticleSystemNode->getAttribute("tween")->getFloatValue();
|
|
|
|
}
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
// ===========================================================================
|
|
|
|
// UnitParticleSystem
|
|
|
|
// ===========================================================================
|
2011-03-14 00:16:07 +01:00
|
|
|
bool UnitParticleSystem::isNight= false;
|
2012-01-07 21:24:54 +01:00
|
|
|
Vec3f UnitParticleSystem::lightColor=Vec3f(1.0f,1.0f,1.0f);
|
2010-03-27 04:09:11 +01:00
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
UnitParticleSystem::UnitParticleSystem(int particleCount):
|
|
|
|
GameParticleSystem(particleCount),
|
|
|
|
parent(NULL){
|
2010-03-27 04:09:11 +01:00
|
|
|
radius= 0.5f;
|
|
|
|
speed= 0.01f;
|
|
|
|
windSpeed= Vec3f(0.0f);
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
setParticleSize(0.6f);
|
|
|
|
setColorNoEnergy(Vec4f(1.0f, 0.5f, 0.0f, 1.0f));
|
2012-01-08 00:53:08 +01:00
|
|
|
sizeNoEnergy=1.0f;
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
primitive= pQuad;
|
|
|
|
gravity= 0.0f;
|
2011-03-14 00:16:07 +01:00
|
|
|
|
|
|
|
fixed= false;
|
2012-01-08 00:53:08 +01:00
|
|
|
shape = UnitParticleSystem::sLinear;
|
|
|
|
angle= 0.0f;
|
2011-03-14 00:16:07 +01:00
|
|
|
rotation= 0.0f;
|
|
|
|
relativeDirection= true;
|
|
|
|
relative= false;
|
|
|
|
staticParticleCount= 0;
|
|
|
|
|
|
|
|
isVisibleAtNight= true;
|
|
|
|
isVisibleAtDay= true;
|
2012-01-07 21:24:54 +01:00
|
|
|
isDaylightAffected= false;
|
2011-03-14 00:16:07 +01:00
|
|
|
|
|
|
|
cRotation= Vec3f(1.0f, 1.0f, 1.0f);
|
|
|
|
fixedAddition= Vec3f(0.0f, 0.0f, 0.0f);
|
2010-09-25 16:38:00 +02:00
|
|
|
//prepare system for given staticParticleCount
|
2011-03-14 00:16:07 +01:00
|
|
|
if(staticParticleCount > 0){
|
|
|
|
emissionState= (float) staticParticleCount;
|
2010-09-25 16:38:00 +02:00
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
energyUp= false;
|
2011-07-07 00:23:51 +02:00
|
|
|
|
|
|
|
delay = 0; // none
|
|
|
|
lifetime = -1; // forever
|
2012-01-08 00:53:08 +01:00
|
|
|
emissionRateFade=0.0f;
|
2011-08-27 08:52:17 +02:00
|
|
|
|
|
|
|
startTime = 0;
|
|
|
|
endTime = 1;
|
2011-10-01 01:55:07 +02:00
|
|
|
|
|
|
|
radiusBasedStartenergy = false;
|
2011-07-07 00:23:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
UnitParticleSystem::~UnitParticleSystem(){
|
|
|
|
if(parent){
|
|
|
|
parent->removeChild(this);
|
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
bool UnitParticleSystem::getVisible() const{
|
|
|
|
if((isNight==true) && (isVisibleAtNight==true)){
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
else if((isNight==false) && (isVisibleAtDay==true)){
|
|
|
|
return visible;
|
|
|
|
}
|
|
|
|
else return false;
|
|
|
|
}
|
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
void UnitParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr) {
|
|
|
|
GameParticleSystem::render(pr,mr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnitParticleSystem::setRotation(float rotation){
|
|
|
|
this->rotation= rotation;
|
2011-09-01 03:11:23 +02:00
|
|
|
for(Children::iterator it= children.begin(); it != children.end(); ++it)
|
2011-07-07 00:23:51 +02:00
|
|
|
(*it)->setRotation(rotation);
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnitParticleSystem::fade(){
|
|
|
|
if(!parent || (lifetime<=0 && !(emissionRateFade && emissionRate > 0))){ // particle has its own lifetime?
|
|
|
|
GameParticleSystem::fade();
|
2011-03-14 00:16:07 +01:00
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
UnitParticleSystem::Shape UnitParticleSystem::strToShape(const string& str){
|
|
|
|
if(str == "spherical"){
|
|
|
|
return sSpherical;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
2011-07-07 00:23:51 +02:00
|
|
|
else if(str == "conical"){
|
|
|
|
return sConical;
|
|
|
|
}
|
|
|
|
else if(str == "linear"){
|
|
|
|
return sLinear;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
else{
|
2011-12-14 07:27:35 +01:00
|
|
|
throw runtime_error("Unknown particle shape: " + str);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnitParticleSystem::initParticle(Particle *p, int particleIndex){
|
|
|
|
ParticleSystem::initParticle(p, particleIndex);
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
const float ang= random.randRange(-2.0f * pi, 2.0f * pi);
|
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
const float mod= streflop::fabsf(static_cast<streflop::Simple>(random.randRange(-radius, radius)));
|
|
|
|
const float radRatio= streflop::sqrtf(static_cast<streflop::Simple>(mod/radius));
|
2010-05-01 22:14:25 +02:00
|
|
|
#else
|
2011-07-07 00:23:51 +02:00
|
|
|
const float mod= fabsf(random.randRange(-radius, radius));
|
2012-02-10 07:21:06 +01:00
|
|
|
const float radRatio= sqrtf(mod / radius);
|
2010-05-01 22:14:25 +02:00
|
|
|
#endif
|
2011-03-14 00:16:07 +01:00
|
|
|
p->color= color;
|
|
|
|
if(radiusBasedStartenergy == true){
|
|
|
|
p->energy= static_cast<int> (maxParticleEnergy * radRatio) + random.randRange(-varParticleEnergy,
|
|
|
|
varParticleEnergy);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
p->energy= static_cast<int> (maxParticleEnergy) + random.randRange(-varParticleEnergy, varParticleEnergy);
|
|
|
|
}
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
p->lastPos= pos;
|
2011-03-14 00:16:07 +01:00
|
|
|
oldPosition= pos;
|
2010-03-27 04:09:11 +01:00
|
|
|
p->size= particleSize;
|
|
|
|
p->accel= Vec3f(0.0f, -gravity, 0.0f);
|
2011-07-07 00:23:51 +02:00
|
|
|
|
|
|
|
// work out where we start for our shape (set speed and pos)
|
|
|
|
switch(shape){
|
|
|
|
case sSpherical:
|
2011-11-17 22:36:29 +01:00
|
|
|
angle = (float)random.randRange(0,360);
|
2011-07-07 00:23:51 +02:00
|
|
|
// fall through
|
|
|
|
case sConical:{
|
|
|
|
Vec2f horiz = Vec2f(1,0).rotate(ang);
|
|
|
|
Vec2f vert = Vec2f(1,0).rotate(degToRad(angle));
|
|
|
|
Vec3f start = Vec3f(horiz.x*vert.y,vert.x,horiz.y).getNormalized(); // close enough
|
|
|
|
p->speed = start * speed;
|
|
|
|
start = start * random.randRange(minRadius,radius);
|
|
|
|
p->pos = pos + offset + start;
|
|
|
|
} break;
|
|
|
|
case sLinear:{
|
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
float x= streflop::sinf(static_cast<streflop::Simple>(ang))*mod;
|
|
|
|
float y= streflop::cosf(static_cast<streflop::Simple>(ang))*mod;
|
2011-07-07 00:23:51 +02:00
|
|
|
#else
|
|
|
|
float x= sinf(ang) * mod;
|
|
|
|
float y= cosf(ang) * mod;
|
|
|
|
#endif
|
|
|
|
const float rad= degToRad(rotation);
|
|
|
|
if(!relative){
|
|
|
|
p->pos= Vec3f(pos.x + x + offset.x, pos.y + random.randRange(-radius / 2, radius / 2) + offset.y, pos.z + y
|
|
|
|
+ offset.z);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
2011-07-07 00:23:51 +02:00
|
|
|
else{// rotate it according to rotation
|
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
p->pos= Vec3f(pos.x+x+offset.z*streflop::sinf(static_cast<streflop::Simple>(rad))+offset.x*streflop::cosf(static_cast<streflop::Simple>(rad)), pos.y+random.randRange(-radius/2, radius/2)+offset.y, pos.z+y+(offset.z*streflop::cosf(static_cast<streflop::Simple>(rad))-offset.x*streflop::sinf(static_cast<streflop::Simple>(rad))));
|
2011-07-07 00:23:51 +02:00
|
|
|
#else
|
|
|
|
p->pos= Vec3f(pos.x + x + offset.z * sinf(rad) + offset.x * cosf(rad), pos.y + random.randRange(-radius / 2,
|
|
|
|
radius / 2) + offset.y, pos.z + y + (offset.z * cosf(rad) - offset.x * sinf(rad)));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
p->speed= Vec3f(direction.x + direction.x * random.randRange(-0.5f, 0.5f), direction.y + direction.y
|
|
|
|
* random.randRange(-0.5f, 0.5f), direction.z + direction.z * random.randRange(-0.5f, 0.5f));
|
|
|
|
p->speed= p->speed * speed;
|
|
|
|
if(relative && relativeDirection){
|
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
p->speed=Vec3f(p->speed.z*streflop::sinf(static_cast<streflop::Simple>(rad))+p->speed.x*streflop::cosf(static_cast<streflop::Simple>(rad)),p->speed.y,(p->speed.z*streflop::cosf(static_cast<streflop::Simple>(rad))-p->speed.x*streflop::sinf(static_cast<streflop::Simple>(rad))));
|
2011-07-07 00:23:51 +02:00
|
|
|
#else
|
2011-03-14 00:16:07 +01:00
|
|
|
p->speed= Vec3f(p->speed.z * sinf(rad) + p->speed.x * cosf(rad), p->speed.y, (p->speed.z * cosf(rad)
|
2011-07-07 00:23:51 +02:00
|
|
|
- p->speed.x * sinf(rad)));
|
|
|
|
#endif
|
2010-05-01 22:14:25 +02:00
|
|
|
}
|
2011-07-07 00:23:51 +02:00
|
|
|
} break;
|
|
|
|
default: throw runtime_error("bad shape");
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnitParticleSystem::update(){
|
2011-07-07 00:23:51 +02:00
|
|
|
// delay and timeline are only applicable for child particles
|
|
|
|
if(parent && delay>0 && delay--){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(parent && lifetime>0 && !--lifetime) {
|
|
|
|
fade();
|
|
|
|
}
|
|
|
|
if(state != sPause) {
|
|
|
|
emissionRate-= emissionRateFade;
|
|
|
|
if(parent && emissionRate < 0.0f) {
|
|
|
|
fade();
|
|
|
|
}
|
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
if(fixed){
|
|
|
|
fixedAddition= Vec3f(pos.x - oldPosition.x, pos.y - oldPosition.y, pos.z - oldPosition.z);
|
|
|
|
oldPosition= pos;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
ParticleSystem::update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void UnitParticleSystem::updateParticle(Particle *p){
|
2011-03-14 00:16:07 +01:00
|
|
|
float energyRatio;
|
|
|
|
if(alternations > 0){
|
|
|
|
int interval= (maxParticleEnergy / alternations);
|
|
|
|
float moduloValue= static_cast<int> (static_cast<float> (p->energy)) % interval;
|
|
|
|
|
|
|
|
if(moduloValue < interval / 2){
|
|
|
|
energyRatio= (interval - moduloValue) / interval;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
energyRatio= moduloValue / interval;
|
|
|
|
}
|
|
|
|
energyRatio= clamp(energyRatio, 0.f, 1.f);
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
energyRatio= clamp(static_cast<float> (p->energy) / maxParticleEnergy, 0.f, 1.f);
|
|
|
|
}
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
p->lastPos+= p->speed;
|
|
|
|
p->pos+= p->speed;
|
2011-03-14 00:16:07 +01:00
|
|
|
if(fixed){
|
2010-03-27 04:09:11 +01:00
|
|
|
p->lastPos+= fixedAddition;
|
|
|
|
p->pos+= fixedAddition;
|
|
|
|
}
|
|
|
|
p->speed+= p->accel;
|
2011-03-14 00:16:07 +01:00
|
|
|
p->color= color * energyRatio + colorNoEnergy * (1.0f - energyRatio);
|
2012-01-08 00:53:08 +01:00
|
|
|
if(isDaylightAffected==true)
|
2012-01-07 21:24:54 +01:00
|
|
|
{
|
|
|
|
p->color.x=p->color.x*lightColor.x;
|
|
|
|
p->color.y=p->color.y*lightColor.y;
|
|
|
|
p->color.z=p->color.z*lightColor.z;
|
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
p->size= particleSize * energyRatio + sizeNoEnergy * (1.0f - energyRatio);
|
|
|
|
if(state == ParticleSystem::sFade || staticParticleCount < 1){
|
2010-09-25 16:38:00 +02:00
|
|
|
p->energy--;
|
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
else{
|
|
|
|
if(maxParticleEnergy > 2){
|
2010-09-25 16:38:00 +02:00
|
|
|
if(energyUp){
|
|
|
|
p->energy++;
|
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
else{
|
2010-09-25 16:38:00 +02:00
|
|
|
p->energy--;
|
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
|
|
|
|
if(p->energy == 1){
|
|
|
|
energyUp= true;
|
2010-09-25 16:38:00 +02:00
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
if(p->energy == maxParticleEnergy){
|
|
|
|
energyUp= false;
|
2010-09-25 16:38:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ================= SET PARAMS ====================
|
|
|
|
|
|
|
|
void UnitParticleSystem::setWind(float windAngle, float windSpeed){
|
2010-05-01 22:14:25 +02:00
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
this->windSpeed.x= streflop::sinf(static_cast<streflop::Simple>(degToRad(windAngle)))*windSpeed;
|
2010-03-27 04:09:11 +01:00
|
|
|
this->windSpeed.y= 0.0f;
|
2012-02-10 07:21:06 +01:00
|
|
|
this->windSpeed.z= streflop::cosf(static_cast<streflop::Simple>(degToRad(windAngle)))*windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
#else
|
2011-03-14 00:16:07 +01:00
|
|
|
this->windSpeed.x= sinf(degToRad(windAngle)) * windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
this->windSpeed.y= 0.0f;
|
2011-03-14 00:16:07 +01:00
|
|
|
this->windSpeed.z= cosf(degToRad(windAngle)) * windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
#endif
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
2012-03-13 22:58:31 +01:00
|
|
|
void UnitParticleSystem::saveGame(XmlNode *rootNode) {
|
|
|
|
std::map<string,string> mapTagReplacements;
|
|
|
|
XmlNode *unitParticleSystemNode = rootNode->addChild("UnitParticleSystem");
|
|
|
|
|
|
|
|
GameParticleSystem::saveGame(unitParticleSystemNode);
|
|
|
|
|
|
|
|
//unitParticleSystemNode->addAttribute("radius",floatToStr(radius), mapTagReplacements);
|
|
|
|
|
|
|
|
// float radius;
|
|
|
|
// float minRadius;
|
|
|
|
// Vec3f windSpeed;
|
|
|
|
// Vec3f cRotation;
|
|
|
|
// Vec3f fixedAddition;
|
|
|
|
// Vec3f oldPosition;
|
|
|
|
// bool energyUp;
|
|
|
|
// float startTime;
|
|
|
|
// float endTime;
|
|
|
|
// bool relative;
|
|
|
|
// bool relativeDirection;
|
|
|
|
// bool fixed;
|
|
|
|
// Shape shape;
|
|
|
|
// float angle;
|
|
|
|
// float sizeNoEnergy;
|
|
|
|
// float gravity;
|
|
|
|
// float rotation;
|
|
|
|
// bool isVisibleAtNight;
|
|
|
|
// bool isVisibleAtDay;
|
|
|
|
// bool isDaylightAffected;
|
|
|
|
// bool radiusBasedStartenergy;
|
|
|
|
// int staticParticleCount;
|
|
|
|
// int delay;
|
|
|
|
// int lifetime;
|
|
|
|
// float emissionRateFade;
|
|
|
|
// GameParticleSystem* parent;
|
|
|
|
|
|
|
|
}
|
|
|
|
void UnitParticleSystem::loadGame(const XmlNode *rootNode) {
|
|
|
|
const XmlNode *unitParticleSystemNode = rootNode;
|
|
|
|
|
|
|
|
GameParticleSystem::loadGame(unitParticleSystemNode);
|
|
|
|
}
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
// ===========================================================================
|
|
|
|
// RainParticleSystem
|
|
|
|
// ===========================================================================
|
|
|
|
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
RainParticleSystem::RainParticleSystem(int particleCount) :
|
|
|
|
ParticleSystem(particleCount){
|
2010-03-27 04:09:11 +01:00
|
|
|
setWind(0.0f, 0.0f);
|
|
|
|
setRadius(20.0f);
|
|
|
|
|
2010-09-24 18:36:59 +02:00
|
|
|
setEmissionRate(25.0f);
|
2010-03-27 04:09:11 +01:00
|
|
|
setParticleSize(3.0f);
|
|
|
|
setColor(Vec4f(0.5f, 0.5f, 0.5f, 0.3f));
|
|
|
|
setSpeed(0.2f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RainParticleSystem::render(ParticleRenderer *pr, ModelRenderer *mr){
|
|
|
|
pr->renderSystemLineAlpha(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RainParticleSystem::initParticle(Particle *p, int particleIndex){
|
|
|
|
ParticleSystem::initParticle(p, particleIndex);
|
|
|
|
|
|
|
|
float x= random.randRange(-radius, radius);
|
|
|
|
float y= random.randRange(-radius, radius);
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
p->color= color;
|
|
|
|
p->energy= 10000;
|
2011-03-14 00:16:07 +01:00
|
|
|
p->pos= Vec3f(pos.x + x, pos.y, pos.z + y);
|
2010-03-27 04:09:11 +01:00
|
|
|
p->lastPos= p->pos;
|
2011-03-14 00:16:07 +01:00
|
|
|
p->speed= Vec3f(random.randRange(-speed / 10, speed / 10), -speed, random.randRange(-speed / 10, speed / 10))
|
|
|
|
+ windSpeed;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool RainParticleSystem::deathTest(Particle *p){
|
2011-03-14 00:16:07 +01:00
|
|
|
return p->pos.y < 0;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void RainParticleSystem::setRadius(float radius){
|
|
|
|
this->radius= radius;
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
|
|
|
|
void RainParticleSystem::setWind(float windAngle, float windSpeed){
|
2010-05-01 22:14:25 +02:00
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
this->windSpeed.x= streflop::sinf(static_cast<streflop::Simple>(degToRad(windAngle)))*windSpeed;
|
2010-03-27 04:09:11 +01:00
|
|
|
this->windSpeed.y= 0.0f;
|
2012-02-10 07:21:06 +01:00
|
|
|
this->windSpeed.z= streflop::cosf(static_cast<streflop::Simple>(degToRad(windAngle)))*windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
#else
|
2011-03-14 00:16:07 +01:00
|
|
|
this->windSpeed.x= sinf(degToRad(windAngle)) * windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
this->windSpeed.y= 0.0f;
|
2011-03-14 00:16:07 +01:00
|
|
|
this->windSpeed.z= cosf(degToRad(windAngle)) * windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
#endif
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
|
|
// SnowParticleSystem
|
|
|
|
// ===========================================================================
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
SnowParticleSystem::SnowParticleSystem(int particleCount) :
|
|
|
|
ParticleSystem(particleCount){
|
2010-03-27 04:09:11 +01:00
|
|
|
setWind(0.0f, 0.0f);
|
|
|
|
setRadius(30.0f);
|
|
|
|
|
2010-09-24 18:36:59 +02:00
|
|
|
setEmissionRate(2.0f);
|
2010-03-27 04:09:11 +01:00
|
|
|
setParticleSize(0.2f);
|
|
|
|
setColor(Vec4f(0.8f, 0.8f, 0.8f, 0.8f));
|
|
|
|
setSpeed(0.05f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SnowParticleSystem::initParticle(Particle *p, int particleIndex){
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
ParticleSystem::initParticle(p, particleIndex);
|
|
|
|
|
|
|
|
float x= random.randRange(-radius, radius);
|
|
|
|
float y= random.randRange(-radius, radius);
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
p->color= color;
|
|
|
|
p->energy= 10000;
|
2011-03-14 00:16:07 +01:00
|
|
|
p->pos= Vec3f(pos.x + x, pos.y, pos.z + y);
|
2010-03-27 04:09:11 +01:00
|
|
|
p->lastPos= p->pos;
|
2011-03-14 00:16:07 +01:00
|
|
|
p->speed= Vec3f(0.0f, -speed, 0.0f) + windSpeed;
|
2010-03-27 04:09:11 +01:00
|
|
|
p->speed.x+= random.randRange(-0.005f, 0.005f);
|
|
|
|
p->speed.y+= random.randRange(-0.005f, 0.005f);
|
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
bool SnowParticleSystem::deathTest(Particle *p){
|
|
|
|
return p->pos.y < 0;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void SnowParticleSystem::setRadius(float radius){
|
|
|
|
this->radius= radius;
|
2011-03-14 00:16:07 +01:00
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
|
|
|
|
void SnowParticleSystem::setWind(float windAngle, float windSpeed){
|
2010-05-01 22:14:25 +02:00
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
this->windSpeed.x= streflop::sinf(static_cast<streflop::Simple>(degToRad(windAngle)))*windSpeed;
|
2010-03-27 04:09:11 +01:00
|
|
|
this->windSpeed.y= 0.0f;
|
2012-02-10 07:21:06 +01:00
|
|
|
this->windSpeed.z= streflop::cosf(static_cast<streflop::Simple>(degToRad(windAngle)))*windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
#else
|
2011-03-14 00:16:07 +01:00
|
|
|
this->windSpeed.x= sinf(degToRad(windAngle)) * windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
this->windSpeed.y= 0.0f;
|
2011-03-14 00:16:07 +01:00
|
|
|
this->windSpeed.z= cosf(degToRad(windAngle)) * windSpeed;
|
2010-05-01 22:14:25 +02:00
|
|
|
#endif
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
|
|
// AttackParticleSystem
|
|
|
|
// ===========================================================================
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
AttackParticleSystem::AttackParticleSystem(int particleCount) :
|
2011-07-07 00:23:51 +02:00
|
|
|
GameParticleSystem(particleCount){
|
2010-03-27 04:09:11 +01:00
|
|
|
primitive= pQuad;
|
|
|
|
gravity= 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
|
|
// ProjectileParticleSystem
|
|
|
|
// ===========================================================================
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
ProjectileParticleSystem::ProjectileParticleSystem(int particleCount) :
|
|
|
|
AttackParticleSystem(particleCount){
|
2010-09-24 18:36:59 +02:00
|
|
|
setEmissionRate(20.0f);
|
2010-03-27 04:09:11 +01:00
|
|
|
setColor(Vec4f(1.0f, 0.3f, 0.0f, 0.5f));
|
|
|
|
setMaxParticleEnergy(100);
|
|
|
|
setVarParticleEnergy(50);
|
|
|
|
setParticleSize(0.4f);
|
|
|
|
setSpeed(0.14f);
|
|
|
|
|
|
|
|
trajectory= tLinear;
|
|
|
|
trajectorySpeed= 1.0f;
|
|
|
|
trajectoryScale= 1.0f;
|
2011-03-14 00:16:07 +01:00
|
|
|
trajectoryFrequency= 1.0f;
|
2011-06-15 00:39:31 +02:00
|
|
|
modelCycle=0.0f;
|
2010-03-27 04:09:11 +01:00
|
|
|
|
|
|
|
nextParticleSystem= NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ProjectileParticleSystem::~ProjectileParticleSystem(){
|
2011-03-14 00:16:07 +01:00
|
|
|
if(nextParticleSystem != NULL){
|
2010-03-27 04:09:11 +01:00
|
|
|
nextParticleSystem->prevParticleSystem= NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectileParticleSystem::link(SplashParticleSystem *particleSystem){
|
|
|
|
nextParticleSystem= particleSystem;
|
2011-06-11 02:26:26 +02:00
|
|
|
nextParticleSystem->setVisible(false);
|
2010-03-27 04:09:11 +01:00
|
|
|
nextParticleSystem->setState(sPause);
|
|
|
|
nextParticleSystem->prevParticleSystem= this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectileParticleSystem::update(){
|
2011-03-14 00:16:07 +01:00
|
|
|
if(state == sPlay){
|
2010-03-27 04:09:11 +01:00
|
|
|
|
|
|
|
lastPos= pos;
|
|
|
|
flatPos+= zVector * trajectorySpeed;
|
|
|
|
Vec3f targetVector= endPos - startPos;
|
|
|
|
Vec3f currentVector= flatPos - startPos;
|
|
|
|
|
|
|
|
// ratio
|
2011-07-19 03:25:38 +02:00
|
|
|
float relative= clamp(currentVector.length() / targetVector.length(), 0.0f, 1.0f);
|
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
float absolute= clamp(streflop::fabs(static_cast<streflop::Simple>(currentVector.length())), 0.0f, 1.0f);
|
2011-07-19 03:25:38 +02:00
|
|
|
#else
|
|
|
|
float absolute= clamp(fabs(currentVector.length()), 0.0f, 1.0f);
|
|
|
|
#endif
|
|
|
|
setTween(relative,absolute);
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
// trajectory
|
2011-06-11 02:26:26 +02:00
|
|
|
switch(trajectory) {
|
2011-03-14 00:16:07 +01:00
|
|
|
case tLinear: {
|
2010-03-27 04:09:11 +01:00
|
|
|
pos= flatPos;
|
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
break;
|
2010-03-27 04:09:11 +01:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
case tParabolic: {
|
2011-07-19 03:25:38 +02:00
|
|
|
float scaledT= 2.0f * (relative - 0.5f);
|
2011-03-14 00:16:07 +01:00
|
|
|
float paraboleY= (1.0f - scaledT * scaledT) * trajectoryScale;
|
2010-03-27 04:09:11 +01:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
pos= flatPos;
|
2010-03-27 04:09:11 +01:00
|
|
|
pos.y+= paraboleY;
|
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
break;
|
2010-03-27 04:09:11 +01:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
case tSpiral: {
|
2010-03-27 04:09:11 +01:00
|
|
|
pos= flatPos;
|
2010-05-01 22:14:25 +02:00
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
pos+= xVector * streflop::cos(static_cast<streflop::Simple>(relative * trajectoryFrequency * targetVector.length())) * trajectoryScale;
|
|
|
|
pos+= yVector * streflop::sin(static_cast<streflop::Simple>(relative * trajectoryFrequency * targetVector.length())) * trajectoryScale;
|
2010-05-01 22:14:25 +02:00
|
|
|
#else
|
2011-07-19 03:25:38 +02:00
|
|
|
pos+= xVector * cos(relative * trajectoryFrequency * targetVector.length()) * trajectoryScale;
|
|
|
|
pos+= yVector * sin(relative * trajectoryFrequency * targetVector.length()) * trajectoryScale;
|
2010-05-01 22:14:25 +02:00
|
|
|
#endif
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
break;
|
2010-03-27 04:09:11 +01:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
default:
|
|
|
|
assert(false);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
direction= pos - lastPos;
|
|
|
|
direction.normalize();
|
2011-07-07 00:23:51 +02:00
|
|
|
// trigger update of child particles
|
|
|
|
positionChildren();
|
|
|
|
rotateChildren();
|
2010-03-27 04:09:11 +01:00
|
|
|
|
|
|
|
//arrive destination
|
2011-03-14 00:16:07 +01:00
|
|
|
if(flatPos.dist(endPos) < 0.5f){
|
2011-07-07 00:23:51 +02:00
|
|
|
fade();
|
2010-03-27 04:09:11 +01:00
|
|
|
model= NULL;
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
if(particleObserver != NULL){
|
2010-03-27 04:09:11 +01:00
|
|
|
particleObserver->update(this);
|
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
if(nextParticleSystem != NULL){
|
2011-06-11 02:26:26 +02:00
|
|
|
nextParticleSystem->setVisible(true);
|
2010-03-27 04:09:11 +01:00
|
|
|
nextParticleSystem->setState(sPlay);
|
|
|
|
nextParticleSystem->setPos(endPos);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ParticleSystem::update();
|
|
|
|
}
|
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
void ProjectileParticleSystem::rotateChildren() {
|
|
|
|
//### only on horizontal plane :(
|
|
|
|
#ifdef USE_STREFLOP
|
2012-02-10 07:21:06 +01:00
|
|
|
float rotation = streflop::atan2(static_cast<streflop::Simple>(direction.x), static_cast<streflop::Simple>(direction.z));
|
2011-07-07 00:23:51 +02:00
|
|
|
#else
|
|
|
|
float rotation = atan2(direction.x, direction.z);
|
|
|
|
#endif
|
|
|
|
rotation = radToDeg(rotation);
|
2011-09-01 03:11:23 +02:00
|
|
|
for(Children::iterator it = children.begin(); it != children.end(); ++it)
|
2011-07-07 00:23:51 +02:00
|
|
|
(*it)->setRotation(rotation);
|
|
|
|
}
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
void ProjectileParticleSystem::initParticle(Particle *p, int particleIndex){
|
|
|
|
|
|
|
|
ParticleSystem::initParticle(p, particleIndex);
|
2011-03-14 00:16:07 +01:00
|
|
|
|
|
|
|
float t= static_cast<float> (particleIndex) / emissionRate;
|
|
|
|
|
|
|
|
p->pos= pos + (lastPos - pos) * t;
|
2010-03-27 04:09:11 +01:00
|
|
|
p->lastPos= lastPos;
|
2011-03-14 00:16:07 +01:00
|
|
|
p->speed= Vec3f(random.randRange(-0.1f, 0.1f), random.randRange(-0.1f, 0.1f), random.randRange(-0.1f, 0.1f))
|
|
|
|
* speed;
|
2010-03-27 04:09:11 +01:00
|
|
|
p->accel= Vec3f(0.0f, -gravity, 0.0f);
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
updateParticle(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectileParticleSystem::updateParticle(Particle *p){
|
2011-03-14 00:16:07 +01:00
|
|
|
float energyRatio= clamp(static_cast<float> (p->energy) / maxParticleEnergy, 0.f, 1.f);
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
p->lastPos+= p->speed;
|
|
|
|
p->pos+= p->speed;
|
|
|
|
p->speed+= p->accel;
|
2011-03-14 00:16:07 +01:00
|
|
|
p->color= color * energyRatio + colorNoEnergy * (1.0f - energyRatio);
|
|
|
|
p->size= particleSize * energyRatio + sizeNoEnergy * (1.0f - energyRatio);
|
2010-03-27 04:09:11 +01:00
|
|
|
p->energy--;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ProjectileParticleSystem::setPath(Vec3f startPos, Vec3f endPos){
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
//compute axis
|
|
|
|
zVector= endPos - startPos;
|
|
|
|
zVector.normalize();
|
|
|
|
yVector= Vec3f(0.0f, 1.0f, 0.0f);
|
|
|
|
xVector= zVector.cross(yVector);
|
2011-03-14 00:16:07 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
//apply offset
|
|
|
|
startPos+= xVector * offset.x;
|
|
|
|
startPos+= yVector * offset.y;
|
|
|
|
startPos+= zVector * offset.z;
|
|
|
|
|
|
|
|
pos= startPos;
|
|
|
|
lastPos= startPos;
|
|
|
|
flatPos= startPos;
|
|
|
|
|
|
|
|
//recompute axis
|
|
|
|
zVector= endPos - startPos;
|
|
|
|
zVector.normalize();
|
|
|
|
yVector= Vec3f(0.0f, 1.0f, 0.0f);
|
|
|
|
xVector= zVector.cross(yVector);
|
|
|
|
|
|
|
|
// set members
|
|
|
|
this->startPos= startPos;
|
|
|
|
this->endPos= endPos;
|
2011-07-07 00:23:51 +02:00
|
|
|
|
|
|
|
// direction
|
|
|
|
direction = (endPos - lastPos);
|
|
|
|
direction.normalize();
|
|
|
|
rotateChildren();
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
ProjectileParticleSystem::Trajectory ProjectileParticleSystem::strToTrajectory(const string &str){
|
2011-03-14 00:16:07 +01:00
|
|
|
if(str == "linear"){
|
2010-03-27 04:09:11 +01:00
|
|
|
return tLinear;
|
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
else if(str == "parabolic"){
|
2010-03-27 04:09:11 +01:00
|
|
|
return tParabolic;
|
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
else if(str == "spiral"){
|
2010-03-27 04:09:11 +01:00
|
|
|
return tSpiral;
|
|
|
|
}
|
|
|
|
else{
|
2011-07-07 00:23:51 +02:00
|
|
|
throw runtime_error("Unknown particle system trajectory: " + str);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
|
|
// SplashParticleSystem
|
|
|
|
// ===========================================================================
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
SplashParticleSystem::SplashParticleSystem(int particleCount) :
|
|
|
|
AttackParticleSystem(particleCount){
|
2010-03-27 04:09:11 +01:00
|
|
|
setColor(Vec4f(1.0f, 0.3f, 0.0f, 0.8f));
|
|
|
|
setMaxParticleEnergy(100);
|
|
|
|
setVarParticleEnergy(50);
|
|
|
|
setParticleSize(1.0f);
|
|
|
|
setSpeed(0.003f);
|
|
|
|
|
|
|
|
prevParticleSystem= NULL;
|
|
|
|
|
|
|
|
emissionRateFade= 1;
|
|
|
|
verticalSpreadA= 1.0f;
|
|
|
|
verticalSpreadB= 0.0f;
|
|
|
|
horizontalSpreadA= 1.0f;
|
|
|
|
horizontalSpreadB= 0.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
SplashParticleSystem::~SplashParticleSystem(){
|
2011-03-14 00:16:07 +01:00
|
|
|
if(prevParticleSystem != NULL){
|
|
|
|
prevParticleSystem->nextParticleSystem= NULL;
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-10 21:44:34 +02:00
|
|
|
void SplashParticleSystem::initParticleSystem() {
|
|
|
|
startEmissionRate = emissionRate;
|
|
|
|
}
|
|
|
|
|
2011-06-11 02:26:26 +02:00
|
|
|
void SplashParticleSystem::update() {
|
2010-03-27 04:09:11 +01:00
|
|
|
ParticleSystem::update();
|
2011-06-10 21:44:34 +02:00
|
|
|
if(state != sPause) {
|
2010-03-27 04:09:11 +01:00
|
|
|
emissionRate-= emissionRateFade;
|
2011-06-10 21:44:34 +02:00
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
float t= 1.0f - ((emissionRate + startEmissionRate) / (startEmissionRate * 2.0f));
|
|
|
|
t= clamp(t, 0.0f, 1.0f);
|
|
|
|
setTween(t,t);
|
2011-06-10 21:44:34 +02:00
|
|
|
|
|
|
|
if(emissionRate < 0.0f) {//otherwise this system lives forever!
|
2010-09-25 16:38:00 +02:00
|
|
|
fade();
|
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SplashParticleSystem::initParticle(Particle *p, int particleIndex){
|
|
|
|
p->pos= pos;
|
|
|
|
p->lastPos= p->pos;
|
|
|
|
p->energy= maxParticleEnergy;
|
|
|
|
p->size= particleSize;
|
|
|
|
p->color= color;
|
2011-03-14 00:16:07 +01:00
|
|
|
|
|
|
|
p->speed= Vec3f(horizontalSpreadA * random.randRange(-1.0f, 1.0f) + horizontalSpreadB, verticalSpreadA
|
|
|
|
* random.randRange(-1.0f, 1.0f) + verticalSpreadB, horizontalSpreadA * random.randRange(-1.0f, 1.0f)
|
|
|
|
+ horizontalSpreadB);
|
2010-03-27 04:09:11 +01:00
|
|
|
p->speed.normalize();
|
|
|
|
p->speed= p->speed * speed;
|
|
|
|
|
|
|
|
p->accel= Vec3f(0.0f, -gravity, 0.0f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SplashParticleSystem::updateParticle(Particle *p){
|
2011-03-14 00:16:07 +01:00
|
|
|
float energyRatio= clamp(static_cast<float> (p->energy) / maxParticleEnergy, 0.f, 1.f);
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
p->lastPos= p->pos;
|
|
|
|
p->pos= p->pos + p->speed;
|
|
|
|
p->speed= p->speed + p->accel;
|
|
|
|
p->energy--;
|
2011-03-14 00:16:07 +01:00
|
|
|
p->color= color * energyRatio + colorNoEnergy * (1.0f - energyRatio);
|
|
|
|
p->size= particleSize * energyRatio + sizeNoEnergy * (1.0f - energyRatio);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
|
|
// ParticleManager
|
|
|
|
// ===========================================================================
|
|
|
|
|
2011-12-02 23:04:02 +01:00
|
|
|
ParticleManager::ParticleManager() {
|
|
|
|
//assert(GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false);
|
|
|
|
}
|
|
|
|
|
|
|
|
ParticleManager::~ParticleManager() {
|
2010-03-27 04:09:11 +01:00
|
|
|
end();
|
|
|
|
}
|
|
|
|
|
|
|
|
void ParticleManager::render(ParticleRenderer *pr, ModelRenderer *mr) const{
|
2011-03-14 00:16:07 +01:00
|
|
|
for(unsigned int i= 0; i < particleSystems.size(); i++){
|
|
|
|
ParticleSystem *ps= particleSystems[i];
|
|
|
|
if(ps != NULL && ps->getVisible()){
|
2010-09-06 19:52:33 +02:00
|
|
|
ps->render(pr, mr);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
bool ParticleManager::hasActiveParticleSystem(ParticleSystem::ParticleSystemType type) const{
|
|
|
|
bool result= false;
|
2011-01-29 04:53:05 +01:00
|
|
|
|
2011-09-01 03:11:23 +02:00
|
|
|
//size_t particleSystemCount= particleSystems.size();
|
|
|
|
//int currentParticleCount= 0;
|
2011-01-29 04:53:05 +01:00
|
|
|
|
|
|
|
vector<ParticleSystem *> cleanupParticleSystemsList;
|
2011-03-14 00:16:07 +01:00
|
|
|
for(unsigned int i= 0; i < particleSystems.size(); i++){
|
|
|
|
ParticleSystem *ps= particleSystems[i];
|
|
|
|
if(ps != NULL){
|
2011-09-01 03:11:23 +02:00
|
|
|
//currentParticleCount+= ps->getAliveParticleCount();
|
2011-03-14 00:16:07 +01:00
|
|
|
|
|
|
|
bool showParticle= true;
|
|
|
|
if(dynamic_cast<UnitParticleSystem *> (ps) != NULL || dynamic_cast<FireParticleSystem *> (ps) != NULL){
|
|
|
|
showParticle= ps->getVisible() || (ps->getState() == ParticleSystem::sFade);
|
2011-01-29 04:53:05 +01:00
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
if(showParticle == true){
|
2011-01-29 04:53:05 +01:00
|
|
|
//printf("Looking for [%d] current id [%d] i = %d\n",type,ps->getParticleSystemType(),i);
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
if(type == ParticleSystem::pst_All || type == ps->getParticleSystemType()){
|
2011-01-29 04:53:05 +01:00
|
|
|
//printf("FOUND particle system type match for [%d] current id [%d] i = %d\n",type,ps->getParticleSystemType(),i);
|
2011-03-14 00:16:07 +01:00
|
|
|
result= true;
|
2011-01-29 04:53:05 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
void ParticleManager::update(int renderFps){
|
2010-08-24 03:21:34 +02:00
|
|
|
Chrono chrono;
|
2011-03-28 05:54:23 +02:00
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled) chrono.start();
|
2010-03-27 04:09:11 +01:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
size_t particleSystemCount= particleSystems.size();
|
|
|
|
int currentParticleCount= 0;
|
2010-09-06 19:52:33 +02:00
|
|
|
|
|
|
|
vector<ParticleSystem *> cleanupParticleSystemsList;
|
2011-03-14 00:16:07 +01:00
|
|
|
for(unsigned int i= 0; i < particleSystems.size(); i++){
|
|
|
|
ParticleSystem *ps= particleSystems[i];
|
2011-11-25 23:38:25 +01:00
|
|
|
if(ps != NULL && validateParticleSystemStillExists(ps) == true) {
|
2011-03-14 00:16:07 +01:00
|
|
|
currentParticleCount+= ps->getAliveParticleCount();
|
|
|
|
|
|
|
|
bool showParticle= true;
|
|
|
|
if(dynamic_cast<UnitParticleSystem *> (ps) != NULL || dynamic_cast<FireParticleSystem *> (ps) != NULL){
|
|
|
|
showParticle= ps->getVisible() || (ps->getState() == ParticleSystem::sFade);
|
2010-08-26 21:01:44 +02:00
|
|
|
}
|
2011-03-14 00:16:07 +01:00
|
|
|
if(showParticle == true){
|
2010-08-26 21:01:44 +02:00
|
|
|
ps->update();
|
2011-05-01 23:46:04 +02:00
|
|
|
if(ps->isEmpty() && ps->getState() == ParticleSystem::sFade){
|
2010-09-06 19:52:33 +02:00
|
|
|
//delete ps;
|
|
|
|
//*it= NULL;
|
|
|
|
cleanupParticleSystemsList.push_back(ps);
|
2010-08-26 21:01:44 +02:00
|
|
|
}
|
2010-08-24 04:49:55 +02:00
|
|
|
}
|
2010-08-24 22:19:30 +02:00
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
2010-09-06 19:52:33 +02:00
|
|
|
//particleSystems.remove(NULL);
|
|
|
|
cleanupParticleSystems(cleanupParticleSystemsList);
|
2010-08-24 03:21:34 +02:00
|
|
|
|
2011-03-28 05:54:23 +02:00
|
|
|
if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0)
|
2011-03-14 00:16:07 +01:00
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld, particleSystemCount = %d, currentParticleCount = %d\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),particleSystemCount,currentParticleCount);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
bool ParticleManager::validateParticleSystemStillExists(ParticleSystem * particleSystem) const{
|
|
|
|
int index= findParticleSystems(particleSystem, this->particleSystems);
|
2010-09-07 19:30:13 +02:00
|
|
|
return (index >= 0);
|
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
int ParticleManager::findParticleSystems(ParticleSystem *psFind, const vector<ParticleSystem *> &particleSystems) const{
|
|
|
|
int result= -1;
|
|
|
|
for(unsigned int i= 0; i < particleSystems.size(); i++){
|
|
|
|
ParticleSystem *ps= particleSystems[i];
|
|
|
|
if(ps != NULL && psFind != NULL && psFind == ps){
|
|
|
|
result= i;
|
2010-09-06 19:52:33 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-07-06 07:16:25 +02:00
|
|
|
void ParticleManager::cleanupParticleSystems(ParticleSystem *ps) {
|
2010-09-06 19:52:33 +02:00
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
int index= findParticleSystems(ps, this->particleSystems);
|
2011-07-06 07:16:25 +02:00
|
|
|
if(ps != NULL && index >= 0) {
|
|
|
|
// printf("-- Delete cleanupParticleSystems [%p]\n",ps);
|
|
|
|
// static map<void *,int> deleteList;
|
|
|
|
// if(deleteList.find(ps) != deleteList.end()) {
|
|
|
|
// assert(deleteList.find(ps) == deleteList.end());
|
|
|
|
// }
|
|
|
|
// deleteList[ps]++;
|
|
|
|
|
2010-09-06 19:52:33 +02:00
|
|
|
delete ps;
|
|
|
|
this->particleSystems.erase(this->particleSystems.begin() + index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
void ParticleManager::cleanupParticleSystems(vector<ParticleSystem *> &particleSystems){
|
2010-09-06 19:52:33 +02:00
|
|
|
|
2011-07-06 07:16:25 +02:00
|
|
|
for(int i= particleSystems.size()-1; i >= 0; i--){
|
2011-03-14 00:16:07 +01:00
|
|
|
ParticleSystem *ps= particleSystems[i];
|
2010-09-06 19:52:33 +02:00
|
|
|
cleanupParticleSystems(ps);
|
|
|
|
}
|
|
|
|
|
|
|
|
particleSystems.clear();
|
|
|
|
//this->particleSystems.remove(NULL);
|
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
void ParticleManager::cleanupUnitParticleSystems(vector<UnitParticleSystem *> &particleSystems){
|
2010-09-06 19:52:33 +02:00
|
|
|
|
2011-07-06 07:16:25 +02:00
|
|
|
for(int i= particleSystems.size()-1; i >= 0; i--){
|
2011-03-14 00:16:07 +01:00
|
|
|
ParticleSystem *ps= particleSystems[i];
|
2010-09-06 19:52:33 +02:00
|
|
|
cleanupParticleSystems(ps);
|
|
|
|
}
|
|
|
|
particleSystems.clear();
|
|
|
|
//this->particleSystems.remove(NULL);
|
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
void ParticleManager::manage(ParticleSystem *ps){
|
2011-07-07 00:23:51 +02:00
|
|
|
assert((std::find(particleSystems.begin(),particleSystems.end(),ps) == particleSystems.end()) && "particle cannot be added twice");
|
2010-03-27 04:09:11 +01:00
|
|
|
particleSystems.push_back(ps);
|
2011-07-07 00:23:51 +02:00
|
|
|
for(int i=ps->getChildCount()-1; i>=0; i--)
|
|
|
|
manage(ps->getChild(i));
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
void ParticleManager::end(){
|
|
|
|
while(particleSystems.empty() == false){
|
2011-07-06 07:16:25 +02:00
|
|
|
ParticleSystem *ps = particleSystems.back();
|
|
|
|
|
|
|
|
// printf("-- Delete end() [%p]\n",ps);
|
|
|
|
// static map<void *,int> deleteList;
|
|
|
|
// if(deleteList.find(ps) != deleteList.end()) {
|
|
|
|
// assert(deleteList.find(ps) == deleteList.end());
|
|
|
|
// }
|
|
|
|
// deleteList[ps]++;
|
|
|
|
|
|
|
|
delete ps;
|
2010-09-06 19:52:33 +02:00
|
|
|
particleSystems.pop_back();
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
}
|
|
|
|
}//end namespace
|