From d2fd71d087a72f67aa158da7a2cdd862db114cbf Mon Sep 17 00:00:00 2001 From: DjWarmonger Date: Sat, 24 May 2014 14:06:08 +0200 Subject: [PATCH] Zone shapes & terrains work nicely. --- lib/mapping/CMapEditManager.cpp | 6 +++ lib/mapping/CMapEditManager.h | 1 + lib/rmg/CMapGenerator.cpp | 3 ++ lib/rmg/CRmgTemplateZone.cpp | 85 +++++++++++++++++++-------------- lib/rmg/CRmgTemplateZone.h | 3 +- lib/rmg/CZonePlacer.cpp | 60 +++++++++++++++++++++++ lib/rmg/CZonePlacer.h | 6 +++ 7 files changed, 126 insertions(+), 38 deletions(-) diff --git a/lib/mapping/CMapEditManager.cpp b/lib/mapping/CMapEditManager.cpp index ef24689cd..e4d079b03 100644 --- a/lib/mapping/CMapEditManager.cpp +++ b/lib/mapping/CMapEditManager.cpp @@ -98,6 +98,12 @@ void CTerrainSelection::deselectRange(const MapRect & rect) }); } +void CTerrainSelection::setSelection(std::vector & vec) +{ + for (auto pos : vec) + this->select(pos); +} + void CTerrainSelection::selectAll() { selectRange(MapRect(int3(0, 0, 0), getMap()->width, getMap()->height)); diff --git a/lib/mapping/CMapEditManager.h b/lib/mapping/CMapEditManager.h index 30abca9f6..3ce839780 100644 --- a/lib/mapping/CMapEditManager.h +++ b/lib/mapping/CMapEditManager.h @@ -91,6 +91,7 @@ public: void deselectRange(const MapRect & rect) override; void selectAll() override; void clearSelection() override; + void setSelection(std::vector & vec); }; /// Selection class to select objects. diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index afb7c8040..2ad0a3c5e 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -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; diff --git a/lib/rmg/CRmgTemplateZone.cpp b/lib/rmg/CRmgTemplateZone.cpp index 26e76f12e..d846f4f01 100644 --- a/lib/rmg/CRmgTemplateZone.cpp +++ b/lib/rmg/CRmgTemplateZone.cpp @@ -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 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 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 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); diff --git a/lib/rmg/CRmgTemplateZone.h b/lib/rmg/CRmgTemplateZone.h index 0272c122f..3d1376635 100644 --- a/lib/rmg/CRmgTemplateZone.h +++ b/lib/rmg/CRmgTemplateZone.h @@ -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 shape); bool fill(CMapGenerator* gen); diff --git a/lib/rmg/CZonePlacer.cpp b/lib/rmg/CZonePlacer.cpp index 52e58f2ad..4cf664b3f 100644 --- a/lib/rmg/CZonePlacer.cpp +++ b/lib/rmg/CZonePlacer.cpp @@ -115,3 +115,63 @@ void CZonePlacer::placeZones(shared_ptr 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 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 Dpair; + std::vector 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; igetPos()))); + } + boost::sort (distances, compareByDistance); + distances.front().first->addTile(pos); //closest tile belongs to zone + } + } + } +} diff --git a/lib/rmg/CZonePlacer.h b/lib/rmg/CZonePlacer.h index 648adb428..b8bbad9f9 100644 --- a/lib/rmg/CZonePlacer.h +++ b/lib/rmg/CZonePlacer.h @@ -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 mapGenOptions, CRandomGenerator * rand); + void assignZones(shared_ptr mapGenOptions); private: + //metric coefiicients + float scaleX; + float scaleY; + float a1, b1, c1, a2, b2, c2; //CMap * map; //unique_ptr graph; CMapGenerator * gen;