From 91bee9f30035293be69d373905eb728babcad91c Mon Sep 17 00:00:00 2001 From: legatt Date: Tue, 20 Jan 2026 12:04:41 +0300 Subject: [PATCH] Optimize vertices --- sdk/map/convert_map.cpp | 125 ++++++++++++++++++++++++++++++---------- sdk/map/provinces.map | Bin 2832 -> 1872 bytes 2 files changed, 95 insertions(+), 30 deletions(-) diff --git a/sdk/map/convert_map.cpp b/sdk/map/convert_map.cpp index 59d2af4..0f288af 100644 --- a/sdk/map/convert_map.cpp +++ b/sdk/map/convert_map.cpp @@ -54,8 +54,13 @@ uint8_t* imageData; uint8_t* tempImageData; size_t width,height,rowSize; -std::unordered_map>,BGRHash> -pixelsPerProvincesPerState; +struct prov +{ + std::vector vertices; + std::vector indices; +}; + +std::unordered_map,BGRHash> pixelsPerProvincesPerState; inline BGR getPixelSafe(size_t r,size_t c){ if(r>=height||c>=width) return EMPTY_COLOR; @@ -93,7 +98,7 @@ void FloodFill(){ if(n%width) q.push(n-1); if(n%width+1&prov,BGR id){ void FindContour(){ for(auto&[state,provs]:pixelsPerProvincesPerState){ for(auto&prov:provs){ - if(prov.empty()) continue; - BGR id=getPixelSafeIndex(prov[0]); - size_t start=FindStart(prov,id); + if(prov.vertices.empty()) continue; + BGR id=getPixelSafeIndex(prov.vertices[0]); + size_t start=FindStart(prov.vertices,id); if(start==std::numeric_limits::max()) continue; std::vector contour; @@ -157,7 +162,7 @@ void FindContour(){ size_t prev = (start % width > 0) ? start - 1 : start + 1; - const size_t MAX=prov.size()*8; + const size_t MAX=prov.vertices.size()*8; for(size_t i=0;i& prov : provs) + for(prov& prov : provs) { - if(prov.size() < 3) + if(prov.vertices.size() < 3) continue; - const size_t n = prov.size(); + const size_t n = prov.vertices.size(); std::vector keep_point(n, true); std::stack> st; @@ -225,9 +230,9 @@ void Aproximate(size_t epsilon) if(keep_point[i]) { double d = PerpendicularDistance( - prov[i], - prov[startIndex], - prov[endIndex], + prov.vertices[i], + prov.vertices[startIndex], + prov.vertices[endIndex], width ); @@ -258,10 +263,10 @@ void Aproximate(size_t epsilon) for(size_t i = 0; i < n; ++i) { if(keep_point[i]) - result.push_back(prov[i]); + result.push_back(prov.vertices[i]); } - prov.swap(result); + prov.vertices.swap(result); } } } @@ -369,12 +374,49 @@ void Triangulate() { for(auto& [state, provs] : pixelsPerProvincesPerState) { - for(std::vector& prov : provs) + for(prov& prov : provs) { - if (prov.size() < 3) + if (prov.vertices.size() < 3) continue; - prov = triangulate_prov(prov, width); + prov.vertices = triangulate_prov(prov.vertices, width); + } + } +} + +void Optimize() +{ + for(auto& [state, provs] : pixelsPerProvincesPerState) + { + for(prov& prov : provs) + { + std::unordered_map vertexToIndex; + vertexToIndex.reserve(prov.vertices.size()); + + std::vector uniqueVertices; + uniqueVertices.reserve(prov.vertices.size()); + + prov.indices.clear(); + + for (size_t v : prov.vertices) + { + auto it = vertexToIndex.find(v); + if (it != vertexToIndex.end()) + { + // вершина уже есть + prov.indices.push_back(it->second); + } + else + { + // новая вершина + uint16_t newIndex = static_cast(uniqueVertices.size()); + uniqueVertices.push_back(v); + vertexToIndex[v] = newIndex; + prov.indices.push_back(newIndex); + } + } + + prov.vertices.swap(uniqueVertices); } } } @@ -382,19 +424,41 @@ void Triangulate() /* ================= OUTPUT ================= */ void GenVertices(std::ofstream&out){ - uint32_t sc=pixelsPerProvincesPerState.size(); - out.write(bytes(&sc),4); - for(auto&[s,provs]:pixelsPerProvincesPerState){ - out.write(bytes(&s),3); - uint32_t pc=provs.size(); - out.write(bytes(&pc),4); - for(auto&p:provs){ - uint32_t vc=p.size(); - out.write(bytes(&vc),4); - for(size_t i:p){ - vertex v{float(i%width),float(i/width)}; + uint32_t statesCount = static_cast(pixelsPerProvincesPerState.size()); + out.write(bytes(&statesCount),4); + + for(auto&[color, provs]:pixelsPerProvincesPerState) + { + out.write(bytes(&color), sizeof(BGR)); + + uint32_t provsCount = static_cast(provs.size()); + out.write(bytes(&provsCount), sizeof(uint32_t)); + + for(prov& prov:provs) + { + //Skip invalid meshes + if (prov.indices.size() % 3 != 0) + { + prov.vertices.clear(); + prov.indices.clear(); + } + + uint32_t verticesCount = static_cast(prov.vertices.size()); + out.write(bytes(&verticesCount), sizeof(uint32_t)); + + for(size_t i: prov.vertices) + { + vertex v{ + static_cast(i%width), + static_cast(i/width) + }; out.write(bytes(&v),sizeof(v)); } + + uint32_t indicesCount = static_cast(prov.indices.size()); + out.write(bytes(&indicesCount), sizeof(uint32_t)); + + out.write(reinterpret_cast(prov.indices.data()), prov.indices.size() * sizeof(uint16_t)); } } } @@ -429,5 +493,6 @@ int main(int argc,char**argv){ FindContour(); Aproximate(1); Triangulate(); + Optimize(); GenVertices(fout); } diff --git a/sdk/map/provinces.map b/sdk/map/provinces.map index c098e6246436b8a2034506f6517b8747f6963137..cdec31f96a660766969e6cc6724c785c1a5b4929 100644 GIT binary patch literal 1872 zcmZ{luWuYj6vvytr2KtVu2fPq0(1q2ub7#KvA zK@+uEJd--Bn2%Z<&5mq;F<#%JKI^4m=~<5|ZWc&G3(oY9ZM zKb=ee1bQ8B-byY+6+K!NcO8qgtF(*Jr`?Yw?m;ZmUP`+hL++IrVMj5>j$?wI#467W z)2_xE_XYZE`Hmxe7@=Pa-@x1G7(GPq(S7s|-6;L*h0Zk(9eG}Ny?7DA>LtRE@r{g#Db>04J#%;?Z_#B#w@8L&i zmDK2A;SM}wT%JNhHywt*4NaT!ViU?%D5-Ycln#|Zl+(QujkwBx$3iHCZnyq zekP-$x6HUTSY<-0Oh}ap@g$D34kuWv&vWIeT1|U_uSySH;=W8PzROx@KQ&$L$qn=t z-9YbyJs++bXuH4#tY44TlUIseqO z2hf9PxtkbIkY(K-DeHtck&?)?M5e_`9G_ zk&n>~?IQb@ncORV-PlG__jSdx(lyJhf!9!tY=2_xEz+Y( z#rgU$KnLg}~ X!mgpUl>2BMyB=34>pu2MT&497Rzb_D literal 2832 zcmZ9Np=%sL6vihdloTQ>Dk4r)gi>)L;tGLoLqtSGMZ}4U6A__AL_}0XoG2wCl!}O> zgtC+pLa7L);#3JGgv!c_ij$G~53b*DcfQNZEWCXC{ob3|nYXi-g_P32G`%P3DpDFg zZzQd+wYnu8R_#51oj12`=eh&wB-A@!a(lG%;&y)f4`OiZq3$c5A?-?iIbU*n=6IT) zf!0+!PbKXIZjU}JIKCE7f!m{h^bB8qUdin%)sNXrR>qyr#y`QPv$d2K6<@P{m#!$x z?a#&fiYvvY;!?4k{o|~Rp{LeQ1;_6wJ_c^jm{H*NtZQFkg|l9-$J~Cb+-|71|Cu@K zXAX}mx&1HIaL!yGJ^Obb(76BUoSOQeX)VW>$53MBo(muIa0mHVmzeTCG<{Lop5ins zJBc0tEKj#`-QQ+4?TcnOhk>UyTHPL|J6^n}DQfAultb2)4zilt55+k!=JtFnG|IZA zdpsW&ORn?$&X?StHM|e?_T-NPw`Z*!q&m-UkJ7Hl@m!5oclTZLnb(c_HQk)k%`<2k z(HaGB#rjg7t>I%Hexf>Z=$Z6L$}3=e%$r-^DSxdx-tfG_+`gZ==W)K|_S>qTgy-6$ z7X`=j3VFSr-+ohkAkLn;AzyO)UY^JG_DkaQ!MZB{TOPfUx<2M3cOChpi1m1SO^ua2 z$0pakZoZcGU(=N^7ur$q`7Z~()IHm|P|z;dyRPK+W7Y12dV79m`+?j45L*e{o;>UE zbM3#0Ee3AS310}@9_^|P?8W;<%{MZ4-rPD=zN7Kzq`Dnv|3LaD%n%F&|O8X*jM2BfSfnC!kH3f$&up+nR_1R&DkQ$Za)y81a7}29@pt{CAX)?3kt@M m6wFUQN^XCs+_j$Tdix`B_G@l`B7QFJ{yT4O<(Tpg+PeSs8rGQr