mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Zone shapes & terrains work nicely.
This commit is contained in:
		| @@ -98,6 +98,12 @@ void CTerrainSelection::deselectRange(const MapRect & rect) | ||||
| 	}); | ||||
| } | ||||
|  | ||||
| void CTerrainSelection::setSelection(std::vector<int3> & vec) | ||||
| { | ||||
| 	for (auto pos : vec) | ||||
| 		this->select(pos); | ||||
| } | ||||
|  | ||||
| void CTerrainSelection::selectAll() | ||||
| { | ||||
| 	selectRange(MapRect(int3(0, 0, 0), getMap()->width, getMap()->height)); | ||||
|   | ||||
| @@ -91,6 +91,7 @@ public: | ||||
| 	void deselectRange(const MapRect & rect) override; | ||||
| 	void selectAll() override; | ||||
| 	void clearSelection() override; | ||||
| 	void setSelection(std::vector<int3> & vec); | ||||
| }; | ||||
|  | ||||
| /// Selection class to select objects. | ||||
|   | ||||
| @@ -154,10 +154,13 @@ void CMapGenerator::genZones() | ||||
|  | ||||
| 	CZonePlacer placer(this); | ||||
| 	placer.placeZones(mapGenOptions, &rand); | ||||
| 	placer.assignZones(mapGenOptions); | ||||
|  | ||||
| 	int i = 0; | ||||
| 	int part_w = w/player_per_side; | ||||
| 	int part_h = h/player_per_side; | ||||
|  | ||||
|  | ||||
| 	for(auto const it : zones) | ||||
| 	{ | ||||
| 		CRmgTemplateZone * zone = it.second; | ||||
|   | ||||
| @@ -294,46 +294,46 @@ void CRmgTemplateZone::setCenter(float3 f) | ||||
|  | ||||
| bool CRmgTemplateZone::pointIsIn(int x, int y) | ||||
| { | ||||
| 	int i, j; | ||||
| 	bool c = false; | ||||
| 	int nvert = shape.size(); | ||||
| 	for (i = 0, j = nvert-1; i < nvert; j = i++) { | ||||
| 		if ( ((shape[i].y>y) != (shape[j].y>y)) && | ||||
| 			(x < (shape[j].x-shape[i].x) * (y-shape[i].y) / (shape[j].y-shape[i].y) + shape[i].x) ) | ||||
| 			c = !c; | ||||
| 	} | ||||
| 	return c; | ||||
| 	//int i, j; | ||||
| 	//bool c = false; | ||||
| 	//int nvert = shape.size(); | ||||
| 	//for (i = 0, j = nvert-1; i < nvert; j = i++) { | ||||
| 	//	if ( ((shape[i].y>y) != (shape[j].y>y)) && | ||||
| 	//		(x < (shape[j].x-shape[i].x) * (y-shape[i].y) / (shape[j].y-shape[i].y) + shape[i].x) ) | ||||
| 	//		c = !c; | ||||
| 	//} | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| void CRmgTemplateZone::setShape(std::vector<int3> shape) | ||||
| { | ||||
| 	int z = -1; | ||||
| 	si32 minx = INT_MAX; | ||||
| 	si32 maxx = -1; | ||||
| 	si32 miny = INT_MAX; | ||||
| 	si32 maxy = -1; | ||||
| 	for(auto &point : shape) | ||||
| 	{ | ||||
| 		if (z == -1) | ||||
| 			z = point.z; | ||||
| 		if (point.z != z) | ||||
| 			throw rmgException("Zone shape points should lie on same z."); | ||||
| 		minx = std::min(minx, point.x); | ||||
| 		maxx = std::max(maxx, point.x); | ||||
| 		miny = std::min(miny, point.y); | ||||
| 		maxy = std::max(maxy, point.y); | ||||
| 	} | ||||
| 	//int z = -1; | ||||
| 	//si32 minx = INT_MAX; | ||||
| 	//si32 maxx = -1; | ||||
| 	//si32 miny = INT_MAX; | ||||
| 	//si32 maxy = -1; | ||||
| 	//for(auto &point : shape) | ||||
| 	//{ | ||||
| 	//	if (z == -1) | ||||
| 	//		z = point.z; | ||||
| 	//	if (point.z != z) | ||||
| 	//		throw rmgException("Zone shape points should lie on same z."); | ||||
| 	//	minx = std::min(minx, point.x); | ||||
| 	//	maxx = std::max(maxx, point.x); | ||||
| 	//	miny = std::min(miny, point.y); | ||||
| 	//	maxy = std::max(maxy, point.y); | ||||
| 	//} | ||||
| 	this->shape = shape; | ||||
| 	for(int x = minx; x <= maxx; ++x) | ||||
| 	{ | ||||
| 		for(int y = miny; y <= maxy; ++y) | ||||
| 		{ | ||||
| 			if (pointIsIn(x, y)) | ||||
| 			{ | ||||
| 				tileinfo[int3(x,y,z)] = CTileInfo(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	//for(int x = minx; x <= maxx; ++x) | ||||
| 	//{ | ||||
| 	//	for(int y = miny; y <= maxy; ++y) | ||||
| 	//	{ | ||||
| 	//		if (pointIsIn(x, y)) | ||||
| 	//		{ | ||||
| 	//			tileinfo[int3(x,y,z)] = CTileInfo(); | ||||
| 	//		} | ||||
| 	//	} | ||||
| 	//} | ||||
| } | ||||
|  | ||||
| int3 CRmgTemplateZone::getPos() | ||||
| @@ -353,11 +353,16 @@ int3 CRmgTemplateZone::getPos() | ||||
| 	//return int3(std::abs(cx/area/6), std::abs(cy/area/6), shape[0].z); | ||||
| 	return pos; | ||||
| } | ||||
| void CRmgTemplateZone::setPos(int3 Pos) | ||||
| void CRmgTemplateZone::setPos(int3 &Pos) | ||||
| { | ||||
| 	pos = Pos; | ||||
| } | ||||
|  | ||||
| void CRmgTemplateZone::addTile (int3 &pos) | ||||
| { | ||||
| 	tileinfo[pos] = CTileInfo(); | ||||
| } | ||||
|  | ||||
| bool CRmgTemplateZone::fill(CMapGenerator* gen) | ||||
| { | ||||
| 	std::vector<CGObjectInstance*> required_objects; | ||||
| @@ -393,7 +398,13 @@ bool CRmgTemplateZone::fill(CMapGenerator* gen) | ||||
| 			playerInfo.posOfMainTown = town->pos - int3(2, 0, 0); | ||||
| 			playerInfo.generateHeroAtMainTown = true; | ||||
|  | ||||
| 			gen->editManager->getTerrainSelection().selectRange(MapRect(shape[0], shape[2].y - shape[0].y, shape[2].x - shape[0].x)); | ||||
| 			//paint zone with matching terrain | ||||
| 			std::vector<int3> tiles; | ||||
| 			for (auto tile : tileinfo) | ||||
| 			{ | ||||
| 				tiles.push_back (tile.first); | ||||
| 			} | ||||
| 			gen->editManager->getTerrainSelection().setSelection(tiles); | ||||
| 			gen->editManager->drawTerrain(VLC->townh->factions[townId]->nativeTerrain, &gen->rand); | ||||
|  | ||||
| 			//required_objects.push_back(town); | ||||
|   | ||||
| @@ -103,8 +103,9 @@ public: | ||||
| 	float3 getCenter() const; | ||||
| 	void setCenter(float3 f); | ||||
| 	int3 getPos(); | ||||
| 	void setPos(int3 pos); | ||||
| 	void setPos(int3 &pos); | ||||
|  | ||||
| 	void addTile (int3 &pos); | ||||
| 	void setShape(std::vector<int3> shape); | ||||
| 	bool fill(CMapGenerator* gen); | ||||
|  | ||||
|   | ||||
| @@ -115,3 +115,63 @@ void CZonePlacer::placeZones(shared_ptr<CMapGenOptions> mapGenOptions, CRandomGe | ||||
| 		logGlobal->infoStream() << boost::format ("Placed zone %d at relative position %s and coordinates %s") % zone.first % zone.second->getCenter() % zone.second->getPos(); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| float CZonePlacer::metric (int3 &A, int3 &B) const | ||||
| { | ||||
| /* | ||||
|  | ||||
| Matlab code | ||||
|  | ||||
| 	dx = abs(A(1) - B(1)); %distance must be symmetric | ||||
| 	dy = abs(A(2) - B(2)); | ||||
|  | ||||
| 	d = 0.01 * dx^3 + 0.1 * dx^2 + 1 * dx + ... | ||||
|     0.03 * dy^3 - 0.3 * dy^2 + 0.3 * dy; | ||||
| */ | ||||
|  | ||||
| 	float dx = abs(A.x - B.x) * scaleX; | ||||
| 	float dy = abs(A.y - B.y) * scaleY; | ||||
|  | ||||
| 	//Horner scheme | ||||
| 	return dx * (1 + dx * (0.1 + dx * 0.01)) + dy * (0.3 + dy * (-0.3 + dy * 0.03)); | ||||
| } | ||||
|  | ||||
| void CZonePlacer::assignZones(shared_ptr<CMapGenOptions> mapGenOptions) | ||||
| { | ||||
| 	auto width = mapGenOptions->getWidth(); | ||||
| 	auto height = mapGenOptions->getHeight(); | ||||
|  | ||||
| 	//scale to Medium map to ensure smooth results | ||||
| 	scaleX = 72.f / width; | ||||
| 	scaleY = 72.f / height; | ||||
|  | ||||
| 	auto zones = gen->getZones(); | ||||
|  | ||||
| 	typedef std::pair<CRmgTemplateZone *, float> Dpair; | ||||
| 	std::vector <Dpair> distances; | ||||
| 	distances.reserve(zones.size()); | ||||
|  | ||||
| 	auto compareByDistance = [](const Dpair & lhs, const Dpair & rhs) -> bool | ||||
| 	{ | ||||
| 		return lhs.second < rhs.second; | ||||
| 	}; | ||||
|  | ||||
| 	int levels = gen->map->twoLevel ? 2 : 1; | ||||
| 	for (int i=0; i<width; i++) | ||||
| 	{ | ||||
| 		for(int j=0; j<height; j++) | ||||
| 		{ | ||||
| 			for (int k = 0; k < levels; k++) | ||||
| 			{ | ||||
| 				distances.clear(); | ||||
| 				int3 pos(i, j, k); | ||||
| 				for (auto zone : zones) | ||||
| 				{ | ||||
| 					distances.push_back (std::make_pair(zone.second, metric(pos, zone.second->getPos()))); | ||||
| 				} | ||||
| 				boost::sort (distances, compareByDistance); | ||||
| 				distances.front().first->addTile(pos); //closest tile belongs to zone | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -40,11 +40,17 @@ class CZonePlacer | ||||
| public: | ||||
| 	explicit CZonePlacer(CMapGenerator * gen); | ||||
| 	int3 cords (float3 f) const; | ||||
| 	float metric (int3 &a, int3 &b) const; | ||||
| 	~CZonePlacer(); | ||||
|  | ||||
| 	void placeZones(shared_ptr<CMapGenOptions> mapGenOptions, CRandomGenerator * rand); | ||||
| 	void assignZones(shared_ptr<CMapGenOptions> mapGenOptions); | ||||
|  | ||||
| private: | ||||
| 	//metric coefiicients | ||||
| 	float scaleX; | ||||
| 	float scaleY; | ||||
| 	float a1, b1, c1, a2, b2, c2; | ||||
| 	//CMap * map; | ||||
| 	//unique_ptr<CZoneGraph> graph; | ||||
| 	CMapGenerator * gen; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user