1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-05 13:04:54 +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 CDrawTerrainOperation::ValidationResult CDrawTerrainOperation::validateTerrainView(const int3 & pos, const TerrainViewPattern & pattern, int recDepth /*= 0*/) const
{ {
auto flippedPattern = pattern;
for(int flip = 0; flip < 4; ++flip) 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) if(valRslt.result)
{ {
valRslt.flip = flip; 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) if(flip == 0)
{ {
return pattern; return pattern;
} }
TerrainViewPattern ret = pattern; //always flip horizontal
if(flip == FLIP_PATTERN_HORIZONTAL || flip == FLIP_PATTERN_BOTH)
{
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
{ {
int y = i * 3; int y = i * 3;
std::swap(ret.data[y], ret.data[y + 2]); std::swap(pattern.data[y], pattern.data[y + 2]);
} }
} //flip vertical only at 2nd step
if(flip == FLIP_PATTERN_VERTICAL || flip == FLIP_PATTERN_BOTH) if(flip == FLIP_PATTERN_VERTICAL)
{ {
for(int i = 0; i < 3; ++i) 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) 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; 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 /// Tests whether the given terrain type is a sand type. Sand types are: Water, Sand and Rock
bool isSandType(ETerrainType terType) const; 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_HORIZONTAL = 1;
static const int FLIP_PATTERN_VERTICAL = 2; static const int FLIP_PATTERN_VERTICAL = 2;

View File

@ -219,6 +219,12 @@ void CMapGenerator::fillZones()
logGlobal->infoStream() << "Started filling zones"; logGlobal->infoStream() << "Started filling zones";
//initialize possible tiles before any object is actually placed
for (auto it : zones)
{
it.second->initFreeTiles(this);
}
createConnections(); createConnections();
//make sure all connections are passable before creating borders //make sure all connections are passable before creating borders
for (auto it : zones) 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) void CRmgTemplateZone::createBorder(CMapGenerator* gen)
{ {
for (auto tile : tileinfo) for (auto tile : tileinfo)
@ -1072,6 +1080,12 @@ void CRmgTemplateZone::createTreasures(CMapGenerator* gen)
do { 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; int3 pos;
if ( ! findPlaceForTreasurePile(gen, minDistance, pos)) if ( ! findPlaceForTreasurePile(gen, minDistance, pos))
{ {
@ -1144,7 +1158,7 @@ void CRmgTemplateZone::createObstacles(CMapGenerator* gen)
if (canObstacleBePlacedHere(gen, temp, obstaclePos)) //can be placed here if (canObstacleBePlacedHere(gen, temp, obstaclePos)) //can be placed here
{ {
auto obj = VLC->objtypeh->getHandlerFor(temp.id, temp.subid)->create(temp); auto obj = VLC->objtypeh->getHandlerFor(temp.id, temp.subid)->create(temp);
placeObject(gen, obj, obstaclePos); placeObject(gen, obj, obstaclePos, false);
return true; return true;
} }
return false; 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 freePaths.insert(pos); //zone center should be always clear to allow other tiles to connect
addAllPossibleObjects (gen); addAllPossibleObjects (gen);
placeMines(gen); placeMines(gen);
createRequiredObjects(gen); createRequiredObjects(gen);
fractalize(gen); //after required objects are created and linked with their own paths 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; bool result = false;
//logGlobal->infoStream() << boost::format("Min dist for density %f is %d") % density % min_dist; //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(); 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; bool allTilesAvailable = true;
gen->foreach_neighbour (tile, [&gen, &allTilesAvailable](int3 neighbour) 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(); //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; //logGlobal->traceStream() << boost::format("Inserting object at %d %d") % pos.x % pos.y;
@ -1364,12 +1379,15 @@ void CRmgTemplateZone::placeObject(CMapGenerator* gen, CGObjectInstance* object,
gen->setOccupied(p, ETileType::USED); gen->setOccupied(p, ETileType::USED);
} }
} }
for(auto tile : tileinfo) 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 si32 d = pos.dist2dSQ(tile); //optimization, only relative distance is interesting
gen->setNearestObjectDistance(tile, std::min(d, gen->getNearestObjectDistance(tile))); gen->setNearestObjectDistance(tile, std::min(d, gen->getNearestObjectDistance(tile)));
} }
} }
}
void CRmgTemplateZone::placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard) void CRmgTemplateZone::placeAndGuardObject(CMapGenerator* gen, CGObjectInstance* object, const int3 &pos, si32 str, bool zoneGuard)
{ {
@ -1461,7 +1479,7 @@ ObjectInfo CRmgTemplateZone::getRandomObject (CMapGenerator* gen, CTreasurePileI
ui32 minValue = 0.25f * value; ui32 minValue = 0.25f * value;
//roulette wheel //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) if (oi.value >= minValue && oi.value <= value && oi.maxPerZone > 0)
{ {

View File

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