- attempt to lessen memory footprint of particles and speed up rendering

This commit is contained in:
Mark Vejvoda 2010-08-24 01:21:34 +00:00
parent 1daecc4145
commit 65cf1bfdac
10 changed files with 180 additions and 74 deletions

View File

@ -173,7 +173,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
bool nodeLimitReached= false;
Node *node= NULL;
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
while(!nodeLimitReached){
@ -219,7 +219,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
}
}//while
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld, openNodes.empty() = %d, pathFound = %d, nodeLimitReached = %d\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),openNodes.empty(),pathFound,nodeLimitReached);
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld, openNodes.empty() = %d, pathFound = %d, nodeLimitReached = %d, unit = %s\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),openNodes.empty(),pathFound,nodeLimitReached,unit->getFullName().c_str());
Node *lastNode= node;
@ -232,7 +232,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
}
}
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//check results of path finding
TravelState ts;
@ -261,7 +261,7 @@ TravelState PathFinder::aStar(Unit *unit, const Vec2i &targetPos){
}
}
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s Line: %d] took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//clean nodes
openNodes.clear();

View File

@ -65,6 +65,8 @@ Game::Game(Program *program, const GameSettings *gameSettings):
renderFps=0;
lastUpdateFps=0;
lastRenderFps=-1;
avgUpdateFps=-1;
avgRenderFps=-1;
paused= false;
gameOver= false;
renderNetworkStatus= false;
@ -556,7 +558,7 @@ void Game::update(){
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
//renderer.updateParticleManager(rsGame,lastRenderFps);
renderer.updateParticleManager(rsGame);
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
@ -665,6 +667,19 @@ void Game::renderWorker() {
// ==================== tick ====================
void Game::tick(){
if(avgUpdateFps == -1) {
avgUpdateFps = updateFps;
}
else {
avgUpdateFps = (avgUpdateFps + updateFps) / 2;
}
if(avgRenderFps == -1) {
avgRenderFps = renderFps;
}
else {
avgRenderFps = (avgRenderFps + renderFps) / 2;
}
lastUpdateFps= updateFps;
lastRenderFps= renderFps;
updateFps= 0;
@ -1317,15 +1332,15 @@ void Game::render2d(){
string str;
if( renderer.getShowDebugUI() == true ||
(perfLogging == true && difftime(time(NULL),lastRenderLog2d) >= 1)) {
str+= "MouseXY: " + intToStr(mouseX) + "," + intToStr(mouseY)+"\n";
str+= "PosObjWord: " + intToStr(gui.getPosObjWorld().x) + "," + intToStr(gui.getPosObjWorld().y)+"\n";
str+= "Render FPS: "+intToStr(lastRenderFps)+"\n";
str+= "Update FPS: "+intToStr(lastUpdateFps)+"\n";
str+= "GameCamera pos: "+floatToStr(gameCamera.getPos().x)+","+floatToStr(gameCamera.getPos().y)+","+floatToStr(gameCamera.getPos().z)+"\n";
str+= "Time: "+floatToStr(world.getTimeFlow()->getTime(),8)+"\n";
str+= "Triangle count: "+intToStr(renderer.getTriangleCount())+"\n";
str+= "Vertex count: "+intToStr(renderer.getPointCount())+"\n";
str+= "Frame count:"+intToStr(world.getFrameCount())+"\n";
str+= "MouseXY: " + intToStr(mouseX) + "," + intToStr(mouseY)+"\n";
str+= "PosObjWord: " + intToStr(gui.getPosObjWorld().x) + "," + intToStr(gui.getPosObjWorld().y)+"\n";
str+= "Render FPS: " + intToStr(lastRenderFps) + "[" + intToStr(avgRenderFps) + "]\n";
str+= "Update FPS: " + intToStr(lastUpdateFps) + "[" + intToStr(avgUpdateFps) + "]\n";
str+= "GameCamera pos: " + floatToStr(gameCamera.getPos().x)+","+floatToStr(gameCamera.getPos().y)+","+floatToStr(gameCamera.getPos().z)+"\n";
str+= "Time: " + floatToStr(world.getTimeFlow()->getTime(),8)+"\n";
str+= "Triangle count: " + intToStr(renderer.getTriangleCount())+"\n";
str+= "Vertex count: " + intToStr(renderer.getPointCount())+"\n";
str+= "Frame count:" + intToStr(world.getFrameCount())+"\n";
//visible quad
Quad2i visibleQuad= renderer.getVisibleQuad();

View File

@ -67,8 +67,8 @@ private:
string loadingText;
int mouse2d;
int mouseX, mouseY; //coords win32Api
int updateFps, lastUpdateFps;
int renderFps, lastRenderFps;
int updateFps, lastUpdateFps, avgUpdateFps;
int renderFps, lastRenderFps, avgRenderFps;
bool paused;
bool gameOver;
bool renderNetworkStatus;

View File

@ -474,8 +474,10 @@ void Renderer::manageParticleSystem(ParticleSystem *particleSystem, ResourceScop
particleManager[rs]->manage(particleSystem);
}
void Renderer::updateParticleManager(ResourceScope rs){
particleManager[rs]->update();
void Renderer::updateParticleManager(ResourceScope rs, int renderFps) {
if(renderFps < 0 || renderFps >= MIN_FPS_NORMAL_RENDERING) {
particleManager[rs]->update();
}
}
void Renderer::renderParticleManager(ResourceScope rs){

View File

@ -286,7 +286,7 @@ public:
Font2D *newFont(ResourceScope rs);
TextRenderer2D *getTextRenderer() const {return textRenderer;}
void manageParticleSystem(ParticleSystem *particleSystem, ResourceScope rs);
void updateParticleManager(ResourceScope rs);
void updateParticleManager(ResourceScope rs,int renderFps=-1);
void renderParticleManager(ResourceScope rs);
void swapBuffers();

View File

@ -904,8 +904,9 @@ bool Unit::update(){
assert(progress<=1.f);
//highlight
if(highlight>0.f){
highlight-= 1.f/(highlightTime*GameConstants::updateFps);
if(highlight>0.f) {
const Game *game = Renderer::getInstance().getGame();
highlight-= 1.f / (highlightTime * game->getWorld()->getUpdateFps(this->getFactionIndex()));
}
if(currSkill == NULL) {
@ -936,8 +937,9 @@ bool Unit::update(){
//update progresses
lastAnimProgress= animProgress;
progress+= (speed*diagonalFactor*heightFactor)/(speedDivider*GameConstants::updateFps);
animProgress+= (currSkill->getAnimSpeed()*heightFactor)/(speedDivider*GameConstants::updateFps);
const Game *game = Renderer::getInstance().getGame();
progress += (speed * diagonalFactor * heightFactor) / (speedDivider * game->getWorld()->getUpdateFps(this->getFactionIndex()));
animProgress += (currSkill->getAnimSpeed() * heightFactor) / (speedDivider * game->getWorld()->getUpdateFps(this->getFactionIndex()));
//update target
updateTarget();
@ -1495,7 +1497,8 @@ void Unit::startDamageParticles(){
if(type->getProperty(UnitType::pBurnable) && fire==NULL){
FireParticleSystem *fps;
fps= new FireParticleSystem(200);
fps->setSpeed(2.5f/GameConstants::updateFps);
const Game *game = Renderer::getInstance().getGame();
fps->setSpeed(2.5f / game->getWorld()->getUpdateFps(this->getFactionIndex()));
fps->setPos(getCurrVector());
fps->setRadius(type->getSize()/3.f);
fps->setTexture(CoreData::getInstance().getFireTexture());
@ -1513,7 +1516,8 @@ void Unit::startDamageParticles(){
ups->setDirection(Vec3f(0,1,-0.2f));
ups->setRadius(type->getSize()/3.f);
ups->setTexture(CoreData::getInstance().getFireTexture());
ups->setSpeed(2.0f/GameConstants::updateFps);
const Game *game = Renderer::getInstance().getGame();
ups->setSpeed(2.0f / game->getWorld()->getUpdateFps(this->getFactionIndex()));
ups->setGravity(0.0004f);
ups->setEmissionRate(1);
ups->setMaxParticleEnergy(150);

View File

@ -48,7 +48,7 @@ World::World(){
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
Config &config= Config::getInstance();
staggeredFactionUpdates = false;
staggeredFactionUpdates = true;
ExploredCellsLookupItemCache.clear();
ExploredCellsLookupItemCacheTimer.clear();
ExploredCellsLookupItemCacheTimerCount = 0;
@ -239,24 +239,51 @@ void World::loadScenario(const string &path, Checksum *checksum){
// ==================== misc ====================
void World::updateAllFactionUnits() {
int factionIdxToTick = -1;
//if(staggeredFactionUpdates == true) {
// factionIdxToTick = tickFactionIndex();
// if(factionIdxToTick < 0) {
// return;
// }
//}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] factionIdxToTick = %d\n",__FILE__,__FUNCTION__,__LINE__,factionIdxToTick);
//units
for(int i=0; i<getFactionCount(); ++i){
for(int j=0; j<getFaction(i)->getUnitCount(); ++j){
unitUpdater.updateUnit(getFaction(i)->getUnit(j));
for(int i=0; i<getFactionCount(); ++i) {
if(factionIdxToTick == -1 || factionIdxToTick == i) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] factionIdxToTick = %d, i = %d\n",__FILE__,__FUNCTION__,__LINE__,factionIdxToTick,i);
for(int j=0; j<getFaction(i)->getUnitCount(); ++j) {
unitUpdater.updateUnit(getFaction(i)->getUnit(j));
}
}
}
}
void World::underTakeDeadFactionUnits() {
int factionIdxToTick = -1;
if(staggeredFactionUpdates == true) {
factionIdxToTick = tickFactionIndex();
if(factionIdxToTick < 0) {
return;
}
}
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] factionIdxToTick = %d\n",__FILE__,__FUNCTION__,__LINE__,factionIdxToTick);
//undertake the dead
for(int i=0; i<getFactionCount(); ++i){
int unitCount = getFaction(i)->getUnitCount();
for(int j= unitCount - 1; j >= 0; j--){
Unit *unit= getFaction(i)->getUnit(j);
if(unit->getToBeUndertaken()) {
unit->undertake();
delete unit;
//j--;
if(factionIdxToTick == -1 || factionIdxToTick == i) {
SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] factionIdxToTick = %d, i = %d\n",__FILE__,__FUNCTION__,__LINE__,factionIdxToTick,i);
int unitCount = getFaction(i)->getUnitCount();
for(int j= unitCount - 1; j >= 0; j--){
Unit *unit= getFaction(i)->getUnit(j);
if(unit->getToBeUndertaken()) {
unit->undertake();
delete unit;
//j--;
}
}
}
}
@ -266,7 +293,7 @@ void World::updateAllFactionConsumableCosts() {
//food costs
for(int i=0; i<techTree->getResourceTypeCount(); ++i){
const ResourceType *rt= techTree->getResourceType(i);
if(rt->getClass()==rcConsumable && frameCount % (rt->getInterval()*GameConstants::updateFps)==0){
if(rt->getClass() == rcConsumable && frameCount % (rt->getInterval() * GameConstants::updateFps)==0){
for(int i=0; i<getFactionCount(); ++i){
getFaction(i)->applyCostsOnInterval();
}
@ -288,13 +315,24 @@ void World::update(){
waterEffects.update();
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//units
updateAllFactionUnits();
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//bool needToUpdateUnits = true;
//if(staggeredFactionUpdates == true) {
// needToUpdateUnits = (frameCount % (GameConstants::updateFps / GameConstants::maxPlayers) == 0);
//}
//undertake the dead
underTakeDeadFactionUnits();
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//if(needToUpdateUnits == true) {
// SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] needToUpdateUnits = %d, frameCount = %d\n",__FILE__,__FUNCTION__,__LINE__,needToUpdateUnits,frameCount);
//units
updateAllFactionUnits();
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//undertake the dead
underTakeDeadFactionUnits();
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
//}
//food costs
updateAllFactionConsumableCosts();
@ -320,6 +358,14 @@ void World::update(){
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis());
}
int World::getUpdateFps(int factionIndex) const {
int result = GameConstants::updateFps;
//if(factionIndex != -1 && staggeredFactionUpdates == true) {
// result = (GameConstants::updateFps / GameConstants::maxPlayers);
//}
return result;
}
bool World::canTickFaction(int factionIdx) {
int factionUpdateInterval = (GameConstants::updateFps / GameConstants::maxPlayers);
int expectedFactionIdx = (frameCount / factionUpdateInterval) -1;
@ -350,7 +396,7 @@ int World::tickFactionIndex() {
void World::tick() {
int factionIdxToTick = -1;
if(staggeredFactionUpdates == true) {
int factionIdxToTick = tickFactionIndex();
factionIdxToTick = tickFactionIndex();
if(factionIdxToTick < 0) {
return;
}

View File

@ -190,6 +190,8 @@ public:
void setFogOfWar(bool value);
std::string DumpWorldToLog(bool consoleBasicInfoOnly = false) const;
int getUpdateFps(int factionIndex) const;
private:
void initCells(bool fogOfWar);

View File

@ -40,7 +40,7 @@ class Model;
// class Particle
// =====================================================
class Particle{
class Particle {
public:
//attributes
Vec3f pos;
@ -52,6 +52,10 @@ public:
int energy;
public:
Particle() {
size = 0;
energy = 0;
}
//get
Vec3f getPos() const {return pos;}
Vec3f getLastPos() const {return lastPos;}
@ -94,7 +98,7 @@ protected:
protected:
Particle *particles;
std::vector<Particle> particles;
RandomGen random;
BlendMode blendMode;
@ -102,7 +106,7 @@ protected:
bool active;
bool visible;
int aliveParticleCount;
int particleCount;
//int particleCount;
Texture *texture;

View File

@ -12,15 +12,19 @@
#include "math_wrapper.h"
#include "particle.h"
#include <stdexcept>
#include <cassert>
#include <algorithm>
#include "util.h"
#include "particle_renderer.h"
#include "math_util.h"
#include "platform_common.h"
#include "leak_dumper.h"
using namespace std;
using namespace Shared::Util;
using namespace Shared::PlatformCommon;
namespace Shared{ namespace Graphics{
@ -28,11 +32,14 @@ namespace Shared{ namespace Graphics{
// class ParticleSystem
// =====================================================
ParticleSystem::ParticleSystem(int particleCount){
ParticleSystem::ParticleSystem(int particleCount) {
//init particle vector
blendMode = bmOne;
particles= new Particle[particleCount];
//particles= new Particle[particleCount];
particles.clear();
particles.reserve(300);
particles.resize(1);
state= sPlay;
aliveParticleCount=0;
active= true;
@ -43,7 +50,8 @@ ParticleSystem::ParticleSystem(int particleCount){
particleObserver= NULL;
//params
this->particleCount= particleCount;
//this->particleCount= particleCount;
//this->particleCount= particles.size();
maxParticleEnergy= 250;
varParticleEnergy= 50;
pos= Vec3f(0.0f);
@ -56,35 +64,38 @@ ParticleSystem::ParticleSystem(int particleCount){
}
ParticleSystem::~ParticleSystem(){
delete [] particles;
//delete [] particles;
particles.clear();
}
// =============== VIRTUAL ======================
//updates all living particles and creates new ones
void ParticleSystem::update(){
void ParticleSystem::update() {
if(aliveParticleCount > particles.size()) {
throw runtime_error("aliveParticleCount >= particles.size()");
}
if(state!=sPause){
for(int i=0; i<aliveParticleCount; ++i){
if(state != sPause){
for(int i = 0; i< aliveParticleCount; ++i) {
updateParticle(&particles[i]);
if(deathTest(&particles[i])){
if(deathTest(&particles[i])) {
//kill the particle
killParticle(&particles[i]);
//mantain alive particles at front of the array
if(aliveParticleCount>0){
particles[i]= particles[aliveParticleCount];
//maintain alive particles at front of the array
if(aliveParticleCount > 0) {
particles[i] = particles[aliveParticleCount-1];
}
}
}
if(state!=sFade){
for(int i=0; i<emissionRate; ++i){
Particle *p= createParticle();
if(state != sFade){
for(int i = 0; i < emissionRate; ++i){
Particle *p = createParticle();
initParticle(p, i);
}
}
@ -185,23 +196,38 @@ int ParticleSystem::isEmpty() const{
Particle * ParticleSystem::createParticle(){
//if any dead particles
if(aliveParticleCount<particleCount){
if(aliveParticleCount < particles.size()) {
++aliveParticleCount;
return &particles[aliveParticleCount-1];
}
//if not
int minEnergy= particles[0].energy;
int minEnergyParticle= 0;
particles.push_back(Particle());
int particleCount = particles.size();
int minEnergy = particles[particleCount-1].energy;
int minEnergyParticle = particleCount-1;
return &particles[minEnergyParticle];
for(int i=0; i<particleCount; ++i){
if(particles[i].energy<minEnergy){
minEnergy= particles[i].energy;
minEnergyParticle= i;
/*
//if any dead particles
if(aliveParticleCount < particleCount) {
++aliveParticleCount;
return &particles[aliveParticleCount-1];
}
//if not
int minEnergy = particles[0].energy;
int minEnergyParticle = 0;
for(int i = 0; i < particleCount; ++i){
if(particles[i].energy < minEnergy){
minEnergy = particles[i].energy;
minEnergyParticle = i;
}
}
return &particles[minEnergyParticle];
*/
}
void ParticleSystem::initParticle(Particle *p, int particleIndex){
@ -888,17 +914,24 @@ void ParticleManager::render(ParticleRenderer *pr, ModelRenderer *mr) const{
}
}
void ParticleManager::update(){
list<ParticleSystem*>::iterator it;
void ParticleManager::update() {
Chrono chrono;
chrono.start();
for (it=particleSystems.begin(); it!=particleSystems.end(); it++){
int particleSystemCount = particleSystems.size();
int particleCount = 0;
list<ParticleSystem*>::iterator it;
for (it=particleSystems.begin(); it!=particleSystems.end(); it++) {
particleCount += (*it)->getAliveParticleCount();
(*it)->update();
if((*it)->isEmpty()){
if((*it)->isEmpty()) {
delete *it;
*it= NULL;
}
}
particleSystems.remove(NULL);
if(chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld, particleSystemCount = %d, particleCount = %d\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis(),particleSystemCount,particleCount);
}
void ParticleManager::manage(ParticleSystem *ps){