From d2802b73f5eff825a4873d3b4577f14364cba856 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 12 Feb 2021 23:40:24 +0100 Subject: [PATCH] Info: make tile existence map mor efficient for sparse worlds Explicitly list the coordinates where tiles exist instead of including a full array with the size of the bounding box. --- src/Info.cpp | 38 ++++++++++++++++++++++---------------- src/Info.hpp | 10 ++++++++-- viewer/MinedMap.js | 21 ++++++++++++++++++++- 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/src/Info.cpp b/src/Info.cpp index a40dd56..913c0f2 100644 --- a/src/Info.cpp +++ b/src/Info.cpp @@ -47,6 +47,9 @@ void Info::writeJSON(const char *filename) const { std::fprintf(f, "\"mipmaps\":["); for (size_t level = 0; level < regions.size(); level++) { + if (level != 0) + std::fprintf(f, ","); + int minX, maxX, minZ, maxZ; std::tie(minX, maxX, minZ, maxZ) = getBounds(level); @@ -57,30 +60,33 @@ void Info::writeJSON(const char *filename) const { std::fprintf(f, "\"minZ\":%i,", minZ); std::fprintf(f, "\"maxZ\":%i", maxZ); std::fprintf(f, "},"); - std::fprintf(f, "\"regions\":["); + std::fprintf(f, "\"regions\":{"); - for (int z = minZ; z <= maxZ; z++) { - std::fprintf(f, "["); + bool first_z = true; + for (const auto &item : regions[level]) { + if (!first_z) + std::fprintf(f, ","); + first_z = false; - for (int x = minX; x <= maxX; x++) { - std::fprintf(f, "%s", regions[level].count(std::make_pair(x, z)) ? "true" : "false"); + int z = item.first; + const std::set &z_regions = item.second; - if (x < maxX) + std::fprintf(f, "\"%d\":[", z); + + bool first_x = true; + for (int x : z_regions) { + if (!first_x) std::fprintf(f, ","); + first_x = false; + + + std::fprintf(f, "%d", x); } - if (z < maxZ) - std::fprintf(f, "],"); - else - std::fprintf(f, "]"); + std::fprintf(f, "]"); } - std::fprintf(f, "]"); - - if (level < regions.size() - 1) - std::fprintf(f, "},"); - else - std::fprintf(f, "}"); + std::fprintf(f, "}}"); } std::fprintf(f, "],"); diff --git a/src/Info.hpp b/src/Info.hpp index 4bc1222..bccabdb 100644 --- a/src/Info.hpp +++ b/src/Info.hpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -39,7 +40,7 @@ namespace MinedMap { class Info { private: - std::vector>> regions; + std::vector>> regions; std::vector> bounds; int32_t spawnX, spawnZ; @@ -54,7 +55,12 @@ public: } void addRegion(int x, int z, size_t level) { - regions[level].insert(std::make_pair(x, z)); + auto &level_r = regions[level]; + auto z_regions = level_r.emplace( + std::piecewise_construct, + std::make_tuple(z), + std::make_tuple()).first; + z_regions->second.insert(x); std::tuple &b = bounds[level]; diff --git a/viewer/MinedMap.js b/viewer/MinedMap.js index f6f444e..8eb4b1f 100644 --- a/viewer/MinedMap.js +++ b/viewer/MinedMap.js @@ -1,3 +1,22 @@ +// bsearch-based array element check +function contains(array, elem) { + var min = 0, max = array.length, i, cur; + + while (min < max) { + i = min + Math.floor((max-min)/2); + cur = array[i]; + + if (cur === elem) + return true; + else if (cur < elem) + min = i + 1; + else + max = i; + } + + return false; +} + var MinedMapLayer = L.GridLayer.extend({ initialize: function (mipmaps, layer) { this.mipmaps = mipmaps; @@ -43,7 +62,7 @@ var MinedMapLayer = L.GridLayer.extend({ if (coords.x >= mipmap.info.minX && coords.x <= mipmap.info.maxX && coords.y >= mipmap.info.minZ && coords.y <= mipmap.info.maxZ && - mipmap.regions[coords.y-mipmap.info.minZ][coords.x-mipmap.info.minX]) + contains(mipmap.regions[coords.y] || [], coords.x)) tile.src = 'data/'+this.layer+'/'+z+'/r.'+coords.x+'.'+coords.y+'.png'; if (z === 0)