1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-26 03:52:01 +02:00

Various optimizations based on RMG profiling.

This commit is contained in:
DjWarmonger 2014-07-24 19:16:49 +02:00
parent 21386081bf
commit 156e19cdf6
5 changed files with 48 additions and 23 deletions

View File

@ -638,9 +638,10 @@ ETerrainGroup::ETerrainGroup CDrawTerrainOperation::getTerrainGroup(ETerrainType
CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainView(const int3 & pos, const TerrainViewPattern & pattern, int recDepth /*= 0*/) const
{
auto flippedPattern = pattern;
for(int flip = 0; flip < 4; ++flip)
{
auto valRslt = validateTerrainViewInner(pos, flip > 0 ? getFlippedPattern(pattern, flip) : pattern, recDepth);
auto valRslt = validateTerrainViewInner(pos, flip > 0 ? flipPattern(flippedPattern, flip) : pattern, recDepth);
if(valRslt.result)
{
valRslt.flip = flip;
@ -795,31 +796,29 @@ bool CDrawTerrainOperation::isSandType(ETerrainType terType) const
}
}
TerrainViewPattern CDrawTerrainOperation::getFlippedPattern(const TerrainViewPattern & pattern, int flip) const
TerrainViewPattern CDrawTerrainOperation::flipPattern(TerrainViewPattern & pattern, int flip) const
{
if(flip == 0)
{
return pattern;
}
TerrainViewPattern ret = pattern;
if(flip == FLIP_PATTERN_HORIZONTAL || flip == FLIP_PATTERN_BOTH)
//always flip horizontal
for(int i = 0; i < 3; ++i)
{
for(int i = 0; i < 3; ++i)
{
int y = i * 3;
std::swap(ret.data[y], ret.data[y + 2]);
}
int y = i * 3;
std::swap(pattern.data[y], pattern.data[y + 2]);
}
if(flip == FLIP_PATTERN_VERTICAL || flip == FLIP_PATTERN_BOTH)
//flip vertical only at 2nd step
if(flip == FLIP_PATTERN_VERTICAL)
{
for(int i = 0; i < 3; ++i)
{
std::swap(ret.data[i], ret.data[6 + i]);
std::swap(pattern.data[i], pattern.data[6 + i]);
}
}
return ret;
return pattern;
}
void CDrawTerrainOperation::invalidateTerrainViews(const int3 & centerPos)

View File

@ -334,7 +334,7 @@ private:
ValidationResult validateTerrainViewInner(const int3 & pos, const TerrainViewPattern & pattern, int recDepth = 0) const;
/// Tests whether the given terrain type is a sand type. Sand types are: Water, Sand and Rock
bool isSandType(ETerrainType terType) const;
TerrainViewPattern getFlippedPattern(const TerrainViewPattern & pattern, int flip) const;
TerrainViewPattern flipPattern(TerrainViewPattern & pattern, int flip) const;
static const int FLIP_PATTERN_HORIZONTAL = 1;
static const int FLIP_PATTERN_VERTICAL = 2;

View File

@ -219,6 +219,12 @@ void CMapGenerator::fillZones()
logGlobal->infoStream() << "Started filling zones";
//initialize possible tiles before any object is actually placed
for (auto it : zones)
{
it.second->initFreeTiles(this);
}
createConnections();
//make sure all connections are passable before creating borders
for (auto it : zones)

View File

@ -378,6 +378,14 @@ void CRmgTemplateZone::discardDistantTiles (CMapGenerator* gen, float distance)
});
}
void CRmgTemplateZone::initFreeTiles (CMapGenerator* gen)
{
vstd::copy_if (tileinfo, vstd::set_inserter(possibleTiles), [gen](const int3 &tile) -> bool
{
return gen->isPossible(tile);
});
}
void CRmgTemplateZone::createBorder(CMapGenerator* gen)
{
for (auto tile : tileinfo)
@ -1072,6 +1080,12 @@ void CRmgTemplateZone::createTreasures(CMapGenerator* gen)
do {
//optimization - don't check tiles which are not allowed
vstd::erase_if (possibleTiles, [gen](const int3 &tile) -> bool
{
return !gen->isPossible(tile);
});
int3 pos;
if ( ! findPlaceForTreasurePile(gen, minDistance, pos))
{
@ -1144,7 +1158,7 @@ void CRmgTemplateZone::createObstacles(CMapGenerator* gen)
if (canObstacleBePlacedHere(gen, temp, obstaclePos)) //can be placed here
{
auto obj = VLC->objtypeh->getHandlerFor(temp.id, temp.subid)->create(temp);
placeObject(gen, obj, obstaclePos);
placeObject(gen, obj, obstaclePos, false);
return true;
}
return false;
@ -1171,6 +1185,7 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen)
freePaths.insert(pos); //zone center should be always clear to allow other tiles to connect
addAllPossibleObjects (gen);
placeMines(gen);
createRequiredObjects(gen);
fractalize(gen); //after required objects are created and linked with their own paths
@ -1188,11 +1203,11 @@ bool CRmgTemplateZone::findPlaceForTreasurePile(CMapGenerator* gen, si32 min_dis
bool result = false;
//logGlobal->infoStream() << boost::format("Min dist for density %f is %d") % density % min_dist;
for(auto tile : tileinfo)
for(auto tile : possibleTiles)
{
auto dist = gen->getTile(tile).getNearestObjectDistance();
if (gen->isPossible(tile) && (dist >= min_dist) && (dist > best_distance))
if ((dist >= min_dist) && (dist > best_distance))
{
bool allTilesAvailable = true;
gen->foreach_neighbour (tile, [&gen, &allTilesAvailable](int3 neighbour)
@ -1347,7 +1362,7 @@ void CRmgTemplateZone::checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance*
//logGlobal->traceStream() << boost::format ("Successfully inserted object (%d,%d) at pos %s") %object->ID %object->subID %pos();
}
void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos)
void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, bool updateDistance)
{
//logGlobal->traceStream() << boost::format("Inserting object at %d %d") % pos.x % pos.y;
@ -1364,10 +1379,13 @@ void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object,
gen->setOccupied(p, ETileType::USED);
}
}
for(auto tile : tileinfo)
{
si32 d = pos.dist2dSQ(tile); //optimization, only relative distance is interesting
gen->setNearestObjectDistance(tile, std::min(d, gen->getNearestObjectDistance(tile)));
if (updateDistance)
{
for(auto tile : possibleTiles) //don't need to mark distance for not possible tiles
{
si32 d = pos.dist2dSQ(tile); //optimization, only relative distance is interesting
gen->setNearestObjectDistance(tile, std::min(d, gen->getNearestObjectDistance(tile)));
}
}
}
@ -1461,7 +1479,7 @@ ObjectInfo CRmgTemplateZone::getRandomObject (CMapGenerator* gen, CTreasurePileI
ui32 minValue = 0.25f * value;
//roulette wheel
for (auto oi : possibleObjects)
for (ObjectInfo &oi : possibleObjects) //copy constructor turned out to be costly
{
if (oi.value >= minValue && oi.value <= value && oi.maxPerZone > 0)
{

View File

@ -145,6 +145,7 @@ public:
void setPos(const int3 &pos);
void addTile (const int3 &pos);
void initFreeTiles (CMapGenerator* gen);
std::set<int3> getTileInfo () const;
void discardDistantTiles (CMapGenerator* gen, float distance);
@ -206,6 +207,7 @@ private:
int3 pos;
float3 center;
std::set<int3> tileinfo; //irregular area assined to zone
std::set<int3> possibleTiles; //optimization purposes for treasure generation
std::vector<TRmgTemplateZoneId> connections; //list of adjacent zones
std::set<int3> freePaths; //core paths of free tiles that all other objects will be linked to
@ -216,6 +218,6 @@ private:
bool findPlaceForTreasurePile(CMapGenerator* gen, si32 min_dist, int3 &pos);
bool canObstacleBePlacedHere(CMapGenerator* gen, ObjectTemplate &temp, int3 &pos);
void checkAndPlaceObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
void placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos);
void placeObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, bool updateDistance = true);
bool guardObject(CMapGenerator* gen, CGObjectInstance* object, si32 str, bool zoneGuard = false);
};