- a better way to cache fog of war and use much less memory

This commit is contained in:
Mark Vejvoda 2013-01-04 18:00:51 +00:00
parent 5a2adde414
commit b96eba3829
6 changed files with 117 additions and 27 deletions

View File

@ -51,6 +51,15 @@ class World;
class Faction;
class GameSettings;
class FowAlphaCellsLookupItem {
public:
std::vector<Vec2i> surfPosList;
std::vector<float> alphaList;
static time_t lastDebug;
};
// =====================================================
// class Faction
//

View File

@ -486,6 +486,8 @@ Unit::Unit(int id, UnitPathInterface *unitpath, const Vec2i &pos,
addItemToVault(&this->hp,this->hp);
addItemToVault(&this->ep,this->ep);
calculateFogOfWarRadius();
// if(isUnitDeleted(this) == true) {
// MutexSafeWrapper safeMutex(&mutexDeletedUnits,string(__FILE__) + "_" + intToStr(__LINE__));
// deletedUnits.erase(this);
@ -1088,9 +1090,53 @@ void Unit::setPos(const Vec2i &pos, bool clearPathFinder) {
// Attempt to improve performance
this->exploreCells();
calculateFogOfWarRadius();
logSynchData(__FILE__,__LINE__);
}
FowAlphaCellsLookupItem Unit::getFogOfWarRadius(bool useCache) const {
if(useCache == true && Config::getInstance().getBool("EnableFowCache","true") == true) {
return cachedFow;
}
FowAlphaCellsLookupItem result;
//iterate through all cells
int sightRange= this->getType()->getSight();
PosCircularIterator pci(map, this->getPos(), sightRange + World::indirectSightRange);
while(pci.next()){
const Vec2i sightpos= pci.getPos();
Vec2i surfPos= Map::toSurfCoords(sightpos);
//compute max alpha
float maxAlpha= 0.0f;
if(surfPos.x > 1 && surfPos.y > 1 && surfPos.x < map->getSurfaceW() -2 && surfPos.y < map->getSurfaceH() -2) {
maxAlpha= 1.f;
}
else if(surfPos.x > 0 && surfPos.y > 0 && surfPos.x < map->getSurfaceW() -1 && surfPos.y < map->getSurfaceH() -1) {
maxAlpha= 0.3f;
}
//compute alpha
float alpha = maxAlpha;
float dist = this->getPos().dist(sightpos);
if(dist > sightRange) {
alpha= clamp(1.f-(dist - sightRange) / (World::indirectSightRange), 0.f, maxAlpha);
}
result.surfPosList.push_back(surfPos);
result.alphaList.push_back(alpha);
}
return result;
}
void Unit::calculateFogOfWarRadius() {
if(game->getWorld()->getFogOfWar() == true) {
if(Config::getInstance().getBool("EnableFowCache","true") == true && this->pos != this->lastPos) {
cachedFow = getFogOfWarRadius(false);
}
}
}
void Unit::setTargetPos(const Vec2i &targetPos) {
if(map->isInside(targetPos) == false || map->isInsideSurface(map->toSurfCoords(targetPos)) == false) {
@ -4279,6 +4325,8 @@ Unit * Unit::loadGame(const XmlNode *rootNode, GameSettings *settings, Faction *
result->pathFindRefreshCellCount = unitNode->getAttribute("pathFindRefreshCellCount")->getIntValue();
}
result->calculateFogOfWarRadius();
return result;
}

View File

@ -456,6 +456,7 @@ private:
RandomGen random;
int pathFindRefreshCellCount;
FowAlphaCellsLookupItem cachedFow;
public:
Unit(int id, UnitPathInterface *path, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing);
@ -478,6 +479,10 @@ public:
inline void incrementPathfindFailedConsecutiveFrameCount() { pathfindFailedConsecutiveFrameCount++; }
inline void resetPathfindFailedConsecutiveFrameCount() { pathfindFailedConsecutiveFrameCount=0; }
const FowAlphaCellsLookupItem & getCachedFow() const { return cachedFow; }
FowAlphaCellsLookupItem getFogOfWarRadius(bool useCache) const;
void calculateFogOfWarRadius();
//queries
Command *getCurrrentCommandThreadSafe();
void setIgnoreCheckCommand(bool value) { ignoreCheckCommand=value;}

View File

@ -47,6 +47,7 @@ class Resource;
class TechTree;
class GameSettings;
class World;
// =====================================================
// class Cell
//

View File

@ -54,7 +54,7 @@ World::World() {
ExploredCellsLookupItemCache.clear();
ExploredCellsLookupItemCacheTimer.clear();
ExploredCellsLookupItemCacheTimerCount = 0;
FowAlphaCellsLookupItemCache.clear();
//FowAlphaCellsLookupItemCache.clear();
// Disable this cache as it takes too much RAM (not sure if its worth the performance gain)
enableFowAlphaCellsLookupItemCache = config.getBool("EnableFowCache","true");
@ -92,7 +92,7 @@ void World::cleanup() {
ExploredCellsLookupItemCache.clear();
ExploredCellsLookupItemCacheTimer.clear();
FowAlphaCellsLookupItemCache.clear();
//FowAlphaCellsLookupItemCache.clear();
if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__);
@ -150,7 +150,7 @@ void World::endScenario() {
ExploredCellsLookupItemCache.clear();
ExploredCellsLookupItemCacheTimer.clear();
FowAlphaCellsLookupItemCache.clear();
//FowAlphaCellsLookupItemCache.clear();
fogOfWarOverride = false;
@ -166,7 +166,7 @@ void World::end(){
ExploredCellsLookupItemCache.clear();
ExploredCellsLookupItemCacheTimer.clear();
FowAlphaCellsLookupItemCache.clear();
//FowAlphaCellsLookupItemCache.clear();
for(int i= 0; i<factions.size(); ++i){
factions[i]->end();
@ -215,7 +215,7 @@ void World::init(Game *game, bool createUnits, bool initFactions){
ExploredCellsLookupItemCache.clear();
ExploredCellsLookupItemCacheTimer.clear();
FowAlphaCellsLookupItemCache.clear();
//FowAlphaCellsLookupItemCache.clear();
this->game = game;
scriptManager= game->getScriptManager();
@ -2238,6 +2238,26 @@ void World::computeFow(int factionIdxToTick) {
if(unit->isOperative()){
int sightRange= unit->getType()->getSight();
if(enableFowAlphaCellsLookupItemCache == true) {
const FowAlphaCellsLookupItem &cellList = unit->getCachedFow();
for(int k = 0; k < cellList.surfPosList.size(); ++k) {
const Vec2i &surfPos = cellList.surfPosList[k];
const float &alpha = cellList.alphaList[k];
minimap.incFowTextureAlphaSurface(surfPos, alpha);
}
}
else {
const FowAlphaCellsLookupItem cellList = unit->getFogOfWarRadius(false);
for(int k = 0; k < cellList.surfPosList.size(); ++k) {
const Vec2i &surfPos = cellList.surfPosList[k];
const float &alpha = cellList.alphaList[k];
minimap.incFowTextureAlphaSurface(surfPos, alpha);
}
}
/*
bool foundInCache = false;
if(enableFowAlphaCellsLookupItemCache == true) {
std::map<Vec2i, std::map<int, FowAlphaCellsLookupItem > >::iterator iterMap = FowAlphaCellsLookupItemCache.find(unit->getPos());
@ -2283,8 +2303,10 @@ void World::computeFow(int factionIdxToTick) {
}
minimap.incFowTextureAlphaSurface(surfPos, alpha);
itemCache.surfPosList.push_back(surfPos);
itemCache.alphaList.push_back(alpha);
if(enableFowAlphaCellsLookupItemCache == true) {
itemCache.surfPosList.push_back(surfPos);
itemCache.alphaList.push_back(alpha);
}
}
if(enableFowAlphaCellsLookupItemCache == true) {
@ -2293,6 +2315,7 @@ void World::computeFow(int factionIdxToTick) {
}
}
}
*/
}
}
}
@ -2403,19 +2426,30 @@ string World::getFowAlphaCellsLookupItemCacheStats() {
int alphaListCount = 0;
//std::map<Vec2i, std::map<int, FowAlphaCellsLookupItem > > FowAlphaCellsLookupItemCache;
for(std::map<Vec2i, std::map<int, FowAlphaCellsLookupItem > >::iterator iterMap1 = FowAlphaCellsLookupItemCache.begin();
iterMap1 != FowAlphaCellsLookupItemCache.end(); ++iterMap1) {
posCount++;
// for(std::map<Vec2i, std::map<int, FowAlphaCellsLookupItem > >::iterator iterMap1 = FowAlphaCellsLookupItemCache.begin();
// iterMap1 != FowAlphaCellsLookupItemCache.end(); ++iterMap1) {
// posCount++;
//
// for(std::map<int, FowAlphaCellsLookupItem >::iterator iterMap2 = iterMap1->second.begin();
// iterMap2 != iterMap1->second.end(); ++iterMap2) {
// sightCount++;
//
// surfPosCount += iterMap2->second.surfPosList.size();
// alphaListCount += iterMap2->second.alphaList.size();
// }
// }
for(int i=0; i<getFactionCount(); ++i) {
Faction *faction= getFaction(i);
if(faction->getTeam() == thisTeamIndex) {
for(int j=0; j<faction->getUnitCount(); ++j) {
const Unit *unit= faction->getUnit(j);
const FowAlphaCellsLookupItem &cache = unit->getCachedFow();
for(std::map<int, FowAlphaCellsLookupItem >::iterator iterMap2 = iterMap1->second.begin();
iterMap2 != iterMap1->second.end(); ++iterMap2) {
sightCount++;
surfPosCount += iterMap2->second.surfPosList.size();
alphaListCount += iterMap2->second.alphaList.size();
surfPosCount += cache.surfPosList.size();
alphaListCount += cache.alphaList.size();
}
}
}
uint64 totalBytes = surfPosCount * sizeof(Vec2i);
totalBytes += alphaListCount * sizeof(float);

View File

@ -76,15 +76,6 @@ public:
static time_t lastDebug;
};
class FowAlphaCellsLookupItem {
public:
std::vector<Vec2i> surfPosList;
std::vector<float> alphaList;
static time_t lastDebug;
};
class World {
private:
typedef vector<Faction *> Factions;
@ -94,7 +85,7 @@ private:
int ExploredCellsLookupItemCacheTimerCount;
bool enableFowAlphaCellsLookupItemCache;
std::map<Vec2i, std::map<int, FowAlphaCellsLookupItem > > FowAlphaCellsLookupItemCache;
//std::map<Vec2i, std::map<int, FowAlphaCellsLookupItem > > FowAlphaCellsLookupItemCache;
public:
static const int generationArea= 100;
@ -283,6 +274,8 @@ public:
std::vector<std::string> validateResourceTypes();
void setFogOfWar(bool value);
bool getFogOfWar() const { return fogOfWar; }
std::string DumpWorldToLog(bool consoleBasicInfoOnly = false) const;
inline int getUpdateFps(int factionIndex) const {