mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Various optimizations based on RMG profiling.
This commit is contained in:
		| @@ -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) | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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) | ||||
| 		{ | ||||
|   | ||||
| @@ -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); | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user