Skip to content

Commit

Permalink
Renamed and added tile and fragment options
Browse files Browse the repository at this point in the history
Tile now controls tiled output. Fragment replaces the old tile option.
  • Loading branch information
spoutn1k committed Dec 16, 2021
1 parent ee6ca97 commit 1dd1331
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 47 deletions.
46 changes: 24 additions & 22 deletions src/cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,30 @@ SETUP_LOGGER
void printHelp(char *binary) {
logger::info(
"Usage: {} <options> WORLDPATH\n\n"
" -from X Z coordinates of the block to start rendering at\n"
" -to X Z coordinates of the block to stop rendering at\n"
" -min/max VAL minimum/maximum Y index of blocks to render\n"
" -file NAME output file; default is 'output.png'\n"
" -colors NAME color file to use; default is 'colors.json'\n"
" -nw -ne -se -sw the orientation of the map\n"
" -nether render the nether\n"
" -end render the end\n"
" -dim[ension] NAME render a dimension by namespaced ID\n"
" -nowater do not render water\n"
" -nobeacons do not render beacon beams\n"
" -shading toggle shading (brightens depending on height)\n"
" -lighting toggle lighting (brightens depending on light)\n"
" -mb int (=3500) use the specified amount of memory (in MB)\n"
" -tile int (=1024) render terrain in tiles of the specified size\n"
" -marker X Z color draw a marker at X Z of the desired color\n"
" -padding int (=5) padding to use around the image\n"
" -h[elp] display an option summary\n"
" -v[erbose] toggle debug mode (-vv for more)\n"
" -dumpcolors dump a json with all defined colors\n"
" -radius VAL radius of the circular render\n"
" -centre|-center X Z coordinates of the centre of circular render\n",
" -from X Z coordinates of the block to start rendering at\n"
" -to X Z coordinates of the block to stop rendering at\n"
" -min/max VAL minimum/maximum Y index of blocks to render\n"
" -file NAME output file; default is 'output.png'\n"
" -colors NAME color file to use; default is 'colors.json'\n"
" -nw -ne -se -sw the orientation of the map\n"
" -nether render the nether\n"
" -end render the end\n"
" -dim[ension] NAME render a dimension by namespaced ID\n"
" -nowater do not render water\n"
" -nobeacons do not render beacon beams\n"
" -shading toggle shading (brightens depending on height)\n"
" -lighting toggle lighting (brightens depending on light)\n"
" -mb int (=3500) use the specified amount of memory (in MB)\n"
" -fragment int (=1024) render terrain in tiles of the specified size\n"
" -tile int (=0) if not 0, will create split output of the "
"desired tile size\n"
" -marker X Z color draw a marker at X Z of the desired color\n"
" -padding int (=5) padding to use around the image\n"
" -h[elp] display an option summary\n"
" -v[erbose] toggle debug mode (-vv for more)\n"
" -dumpcolors dump a json with all defined colors\n"
" -radius VAL radius of the circular render\n"
" -centre|-center X Z coordinates of the centre of circular render\n",
binary);
}

Expand Down
3 changes: 2 additions & 1 deletion src/include/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ struct Coordinates {
#undef BYTESPERPIXEL
}

void tile(std::vector<Coordinates<Integer>> &fragments, size_t size) const {
void fragment(std::vector<Coordinates<Integer>> &fragments,
size_t size) const {
for (Integer x = minX; x <= maxX; x += size) {
for (Integer z = minZ; z <= maxZ; z += size) {
Coordinates<Integer> fragment = *this;
Expand Down
44 changes: 28 additions & 16 deletions src/mcmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,29 @@ int render(const Settings::WorldOptions &options, const Colors::Palette &colors,
logger::debug("Rendering {} with {}\n", options.save.name,
options.boundaries.to_string());

// Split terrain according to tile size
std::vector<World::Coordinates> tiles;
options.boundaries.tile(tiles, options.tile_size);
// Divide terrain according to fragment size
std::vector<World::Coordinates> fragment_coordinates;
options.boundaries.fragment(fragment_coordinates, options.fragment_size);

std::vector<Canvas> fragments(tiles.size());
std::vector<Canvas> fragments(fragment_coordinates.size());

Progress::Status s = Progress::Status(tiles.size(), cb, Progress::RENDERING);
Progress::Status s =
Progress::Status(fragment_coordinates.size(), cb, Progress::RENDERING);

// This value represents the amount of canvasses that can fit in memory at
// once to avoid going over the limit of RAM
Counter<size_t> capacity = memory_capacity(
options.mem_limit, tiles[0].footprint(), tiles.size(), THREADS);
Counter<size_t> capacity =
memory_capacity(options.mem_limit, fragment_coordinates[0].footprint(),
fragment_coordinates.size(), THREADS);

if (!capacity)
return false;

logger::debug("Memory capacity: {} tiles - {} tiles scheduled\n",
size_t(capacity), tiles.size());
logger::debug("Memory capacity: {} fragments - {} fragments scheduled\n",
size_t(capacity), fragment_coordinates.size());

// If caching is needed, ensure the cache directory is available
if (capacity < tiles.size())
if (capacity < fragments.size())
if (!prepare_cache(getTempDir()))
return false;

Expand All @@ -46,14 +48,14 @@ int render(const Settings::WorldOptions &options, const Colors::Palette &colors,
#ifdef _OPENMP
#pragma omp for ordered schedule(dynamic)
#endif
for (OMP_FOR_INDEX i = 0; i < tiles.size(); i++) {
logger::debug("Rendering {}\n", tiles[i].to_string());
for (OMP_FOR_INDEX i = 0; i < fragment_coordinates.size(); i++) {
logger::debug("Rendering {}\n", fragment_coordinates[i].to_string());
IsometricCanvas canvas;
canvas.setMap(tiles[i]);
canvas.setMap(fragment_coordinates[i]);
canvas.setColors(colors);

// Load the minecraft terrain to render
Terrain::Data world(tiles[i], options.regionDir(), colors);
Terrain::Data world(fragment_coordinates[i], options.regionDir(), colors);

// Draw the terrain fragment
canvas.shading = options.shading;
Expand Down Expand Up @@ -99,10 +101,20 @@ int render(const Settings::WorldOptions &options, const Colors::Palette &colors,
}

begin = std::chrono::high_resolution_clock::now();
if (!merged.save(options.outFile, options.padding, cb))
return false;

bool save_status;

if (options.tile_size) {
save_status = merged.tile(options.outFile, options.tile_size, cb);
} else {
save_status = merged.save(options.outFile, options.padding, cb);
}

end = std::chrono::high_resolution_clock::now();

if (!save_status)
return false;

logger::debug(
"Drawn PNG in {}ms\n",
std::chrono::duration_cast<std::chrono::milliseconds>(end - begin)
Expand Down
23 changes: 21 additions & 2 deletions src/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ bool Settings::parseArgs(int argc, char **argv, Settings::WorldOptions *opts) {
return false;
}
opts->tile_size = atoi(NEXTARG);
} else if (strcmp(option, "-fragment") == 0) {
if (!MOREARGS(1) || !isNumeric(POLLARG(1))) {
logger::error("{} needs an integer\n", option);
return false;
}
opts->fragment_size = atoi(NEXTARG);
} else if (strcmp(option, "-help") == 0 || strcmp(option, "-h") == 0) {
opts->mode = Settings::HELP;
return false;
Expand Down Expand Up @@ -188,10 +194,23 @@ bool Settings::parseArgs(int argc, char **argv, Settings::WorldOptions *opts) {
return false;
}

if (opts->tile_size < 16) {
logger::error("Cannot render tiles this small\n");
if (opts->fragment_size < 16) {
logger::error("Cannot render map fragments this small\n");
return false;
}

if (opts->tile_size) {
if (opts->padding != PADDING_DEFAULT && opts->padding) {
logger::error("Cannot pad tiled output !\n");
return false;
}

if (opts->outFile == OUTPUT_DEFAULT) {
opts->outFile = OUTPUT_TILED_DEFAULT;

fs::create_directory(opts->outFile);
}
}
}

return true;
Expand Down
20 changes: 14 additions & 6 deletions src/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
#define UNDEFINED 0x7FFFFFFF

namespace Settings {
const string OUTPUT_DEFAULT = "output.png";
const string OUTPUT_TILED_DEFAULT = "output";
const size_t PADDING_DEFAULT = 5;
const size_t TILE_SIZE_DEFAULT = 0;

enum Action { RENDER, DUMPCOLORS, HELP };

Expand All @@ -28,32 +32,36 @@ struct WorldOptions {
World::Coordinates boundaries;

// Image settings
uint16_t padding; // Should be enough
uint16_t padding;
bool hideWater, hideBeacons, shading, lighting;
size_t tile_size; // 0 means no tiling

// Marker storage
uint8_t totalMarkers;
std::array<Colors::Marker, 256> markers;

// Memory limits, legacy code for image splitting
// Memory limits
size_t mem_limit;
size_t tile_size;
size_t fragment_size;

WorldOptions()
: mode(RENDER), outFile("output.png"), colorFile(""), save(),
: mode(RENDER), outFile(OUTPUT_DEFAULT), colorFile(""), save(),
dim("overworld") {

boundaries.setUndefined();
boundaries.minY = mcmap::constants::min_y;
boundaries.maxY = mcmap::constants::max_y;

hideWater = hideBeacons = shading = lighting = false;
padding = 5;
padding = PADDING_DEFAULT;
tile_size = TILE_SIZE_DEFAULT;

totalMarkers = 0;

// Default 3.5G of memory maximum
mem_limit = 3500 * uint64_t(1024 * 1024);
tile_size = 1024;
// Render whole regions at once
fragment_size = 1024;
}

fs::path regionDir() const;
Expand Down

0 comments on commit 1dd1331

Please sign in to comment.