SHARE
TWEET

WIP heightmap.cpp

a guest Jan 4th, 2020 6 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * This file is part of OpenTTD.
  3.  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
  4.  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  5.  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
  6.  */
  7.  
  8. /** @file heightmap.cpp Creating of maps from heightmaps. */
  9.  
  10. #include "stdafx.h"
  11. #include "heightmap.h"
  12. #include "clear_map.h"
  13. #include "void_map.h"
  14. #include "error.h"
  15. #include "saveload/saveload.h"
  16. #include "bmp.h"
  17. #include "gfx_func.h"
  18. #include "fios.h"
  19. #include "fileio_func.h"
  20. #include "core/random_func.hpp"
  21.  
  22. #include "table/strings.h"
  23.  
  24. #include "safeguards.h"
  25.  
  26. #include <vector>
  27.  
  28. namespace openttd
  29. {
  30.     // vector of 8-bit word per pixel linear bitmaps
  31.     using bitmaps8_t = std::vector<std::vector<byte>>;
  32. }
  33.  
  34. /**
  35.  * Convert RGB colours to Grayscale using 29.9% Red, 58.7% Green, 11.4% Blue
  36.  *  (average luminosity formula, NTSC Colour Space)
  37.  */
  38. static inline byte RGBToGrayscale(byte red, byte green, byte blue)
  39. {
  40.     /* To avoid doubles and stuff, multiply it with a total of 65536 (16bits), then
  41.      *  divide by it to normalize the value to a byte again. */
  42.     return ((red * 19595) + (green * 38470) + (blue * 7471)) / 65536;
  43. }
  44.  
  45.  
  46. #ifdef WITH_PNG
  47.  
  48. #include <png.h>
  49.  
  50. template <typename T, typename OP>
  51. void copy_bitmap_data_from_rows(openttd::bitmaps8_t &maps, const uint channels,
  52.     const png_uint_32 width, const png_uint_32 height,
  53.     png_bytep *row_pointers, OP &transform_operator)
  54. {
  55.     if (transform_operator.needs_measurement()) {
  56.         for (uint y = 0; y < height; y++) {
  57.             const T *row_ptr = (const T *)row_pointers[y];
  58.             for (uint x = 0; x < width; x++) {
  59.                 for (uint i = 0; i < channels; i++) {
  60.                     transform_operator.measure(i, x, y, *row_ptr);
  61.                     row_ptr++;
  62.                 }
  63.             }
  64.         }
  65.     }
  66.  
  67.     uint dest_offset = 0;
  68.     for (uint y = 0; y < height; y++) {
  69.         const T *row_ptr = (const T *)row_pointers[y];
  70.         for (uint x = 0; x < width; x++) {
  71.             for (uint i = 0; i < channels; i++) {
  72.                 maps[i][dest_offset] = transform_operator(i, x, y, *row_ptr);
  73.                 row_ptr++;
  74.             }
  75.             dest_offset++;
  76.         }
  77.     }
  78. }
  79.  
  80. // data-type transform operator functor
  81. //
  82. struct toperator_t
  83. {
  84.     // pure overloads, NO VIRTUAL
  85.     toperator_t() {}
  86.     bool needs_measurement() { return false; }
  87.     void measure(uint i, uint x, uint y, byte z) {}
  88.     byte operator()(uint i, uint x, uint y, byte z) { return 0; }
  89. };
  90.  
  91. // 8-bit input, do nothing (copy)
  92. struct toperator_8bit_copy_t : toperator_t
  93. {
  94.     toperator_8bit_copy_t() : min_z(256), max_z(0) {}
  95.     bool needs_measurement() { return false; }
  96.     void measure(uint i, uint x, uint y, byte z)
  97.     {
  98.         if (i == 0) {
  99.             if (z > max_z) {
  100.                 max_z = z;
  101.             } else if (z < min_z) {
  102.                 min_z = z;
  103.             }
  104.         }
  105.     }
  106.     byte operator()(uint i, uint x, uint y, byte z)
  107.     {
  108.         if (z > min_z) {
  109.             //float normalized = float(z - min_z) / float(max_z - min_z);
  110.             //int out_z = z;//1 + int(normalized * 254.0f + 0.5f);
  111.             //assert(out_z >= 0 && out_z < 256);
  112.             return z;
  113.         }
  114.         return 0;
  115.     }
  116.     int min_z;
  117.     int max_z;
  118. };
  119.  
  120. // 8-bit index, translate via palette table
  121. struct toperator_8bit_indexed_t : toperator_t
  122. {
  123.     toperator_8bit_indexed_t(byte *palette_ptr) : palette(palette_ptr) {}
  124.     byte operator()(uint i, uint x, uint y, byte z)
  125.     {
  126.         return palette[z];
  127.     }
  128.     byte *palette;
  129. };
  130.  
  131. // conditionally limit to inclusive range
  132. template <typename T>
  133. T limit_inclusive(T x, T minimum, T maximum)
  134. {
  135.     return x < minimum ? minimum : x > maximum ? maximum : x;
  136. }
  137.  
  138. // MSB/LSB first conversion
  139. std::uint16_t flip_endian(std::uint16_t x)
  140. {
  141.     return ((x >> 8) & 0xFF) | ((x << 8) & 0xFF00);
  142. }
  143.  
  144. struct minmax_t
  145. {
  146.     minmax_t() : min(INT_MAX), max(INT_MIN)
  147.     {
  148.     }
  149.     void operator()(int x)
  150.     {
  151.         if (x > max) {
  152.             max = x;
  153.         }
  154.         if (x < min) {
  155.             min = x;
  156.         }
  157.     }
  158.     int min;
  159.     int max;
  160. };
  161.  
  162. // 16-bit input, limit range
  163. template <typename T>
  164. struct toperator_16bit_copy_t : toperator_t
  165. {
  166.     toperator_16bit_copy_t() : neg_z(32767) {}
  167.     bool needs_measurement() { return false; }
  168.     void measure(uint i, uint x, uint y, T z)
  169.     {
  170.         // PNG 16-bit is MSB first
  171.         z = flip_endian(z);
  172.         switch (i) {
  173.             case 0:
  174.                 if (z < 32768) {
  175.                     mm[i](z);
  176.                 }
  177.                 if (z < neg_z) {
  178.                     neg_z = z;
  179.                 }
  180.                 break;
  181.  
  182.             case 1:
  183.             case 2:
  184.                 mm[i](z);
  185.                 break;
  186.         }
  187.     }
  188.  
  189.     byte operator()(uint i, uint x, uint y, T z)
  190.     {
  191.         // PNG 16-bit is MSB first
  192.         z = flip_endian(z);
  193.         if (i == 0) {
  194.             if (z > 0) {
  195. #if _DEBUG && 0
  196.                 if (z < 0 || z > 255) {
  197.                     __debugbreak();
  198.                 }
  199. #endif
  200.                 //float normalized = float(z - min_z) / float(max_z - min_z);
  201.                 //int out_z = 1 + int(normalized * 254.0f + 0.5f);
  202.                 const int scaled_height = 1 + ((z - 1) * _settings_game.construction.max_heightlevel) / 255;
  203.                 return limit_inclusive<T>(scaled_height, 1, 255);
  204.  
  205.                 //return limit_inclusive<T>(z, 0, 255);
  206.             }
  207.             return 0;
  208.         } else {
  209.             return limit_inclusive<T>(z, 0, 255);
  210.         }
  211.     }
  212.     int neg_z;
  213.     minmax_t mm[3];
  214. };
  215.  
  216. /**
  217.  * The PNG Heightmap loader.
  218.  */
  219. static void ReadHeightmapPNGImageData(openttd::bitmaps8_t &maps, png_structp png_ptr, png_infop info_ptr)
  220. {
  221.     byte gray_palette[256];
  222.     png_bytep *row_pointers = nullptr;
  223.     bool has_palette = png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE;
  224.     uint channels = png_get_channels(png_ptr, info_ptr);
  225.  
  226.     const png_uint_32 width = png_get_image_width(png_ptr, info_ptr);
  227.     const png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
  228.    
  229.     /* Get palette and convert it to grayscale */
  230.     if (has_palette) {
  231.         int i;
  232.         int palette_size;
  233.         png_color *palette;
  234.         bool all_gray = true;
  235.  
  236.         png_get_PLTE(png_ptr, info_ptr, &palette, &palette_size);
  237.         for (i = 0; i < palette_size && (palette_size != 16 || all_gray); i++) {
  238.             all_gray &= palette[i].red == palette[i].green && palette[i].red == palette[i].blue;
  239.             gray_palette[i] = RGBToGrayscale(palette[i].red, palette[i].green, palette[i].blue);
  240.         }
  241.  
  242.         /**
  243.          * For a non-gray palette of size 16 we assume that
  244.          * the order of the palette determines the height;
  245.          * the first entry is the sea (level 0), the second one
  246.          * level 1, etc.
  247.          */
  248.         if (palette_size == 16 && !all_gray) {
  249.             for (i = 0; i < palette_size; i++) {
  250.                 gray_palette[i] = 256 * i / palette_size;
  251.             }
  252.         }
  253.     }
  254.  
  255.     row_pointers = png_get_rows(png_ptr, info_ptr);
  256.  
  257.     if (has_palette) {
  258.         switch (png_get_bit_depth(png_ptr, info_ptr)) {
  259.             case 8:
  260.                 copy_bitmap_data_from_rows<byte>(maps, channels, width, height, row_pointers,
  261.                     toperator_8bit_indexed_t(gray_palette));
  262.                 break;
  263.  
  264.             default:
  265.                 // failure, unhandled bit depth
  266.                 __debugbreak();
  267.                 break;
  268.         }
  269.     } else {
  270.         switch (png_get_bit_depth(png_ptr, info_ptr)) {
  271.             case 16:
  272.                 copy_bitmap_data_from_rows<std::uint16_t>(maps, channels, width, height, row_pointers,
  273.                     toperator_16bit_copy_t<std::uint16_t>());
  274.                 break;
  275.  
  276.             case 8:
  277.                 copy_bitmap_data_from_rows<byte>(maps, channels, width, height, row_pointers,
  278.                     toperator_8bit_copy_t());
  279.                 break;
  280.  
  281.             default:
  282.                 // failure, unhandled bit depth
  283.                 __debugbreak();
  284.                 break;
  285.         }
  286.     }
  287. }
  288.  
  289. /**
  290.  * Reads the heightmap and/or size of the heightmap from a PNG file.
  291.  * If map == nullptr only the size of the PNG is read, otherwise a map
  292.  * with grayscale pixels is allocated and assigned to *map.
  293.  */
  294. static bool ReadHeightmapPNG(const char *filename, uint *x, uint *y, openttd::bitmaps8_t *maps_ptr)
  295. {
  296.     FILE *fp;
  297.     png_structp png_ptr = nullptr;
  298.     png_infop info_ptr  = nullptr;
  299.  
  300.     fp = FioFOpenFile(filename, "rb", HEIGHTMAP_DIR);
  301.     if (fp == nullptr) {
  302.         ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_FILE_NOT_FOUND, WL_ERROR);
  303.         return false;
  304.     }
  305.  
  306.     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
  307.     if (png_ptr == nullptr) {
  308.         ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, WL_ERROR);
  309.         fclose(fp);
  310.         return false;
  311.     }
  312.  
  313.     info_ptr = png_create_info_struct(png_ptr);
  314.     if (info_ptr == nullptr || setjmp(png_jmpbuf(png_ptr))) {
  315.         ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_MISC, WL_ERROR);
  316.         fclose(fp);
  317.         png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
  318.         return false;
  319.     }
  320.  
  321.     png_init_io(png_ptr, fp);
  322.  
  323.     /* Allocate memory and read image, without alpha or 16-bit samples
  324.      * (result is either 8-bit indexed/grayscale or 24-bit RGB) */
  325.     png_set_packing(png_ptr);
  326.     png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_PACKING, nullptr);
  327.  
  328.     const png_byte channels = png_get_channels(png_ptr, info_ptr);
  329.  
  330. #if 0
  331.     /* Maps of wrong colour-depth are not used.
  332.      * (this should have been taken care of by stripping alpha and 16-bit samples on load) */
  333.     if ((png_get_channels(png_ptr, info_ptr) != 1) && (png_get_channels(png_ptr, info_ptr) != 3) && (png_get_bit_depth(png_ptr, info_ptr) != 8)) {
  334.         ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_PNGMAP_IMAGE_TYPE, WL_ERROR);
  335.         fclose(fp);
  336.         png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
  337.         return false;
  338.     }
  339. #endif
  340.  
  341.     uint width = png_get_image_width(png_ptr, info_ptr);
  342.     uint height = png_get_image_height(png_ptr, info_ptr);
  343.  
  344.     /* Check if image dimensions don't overflow a size_t to avoid memory corruption. */
  345.     if ((uint64)width * height >= (size_t)-1) {
  346.         ShowErrorMessage(STR_ERROR_PNGMAP, STR_ERROR_HEIGHTMAP_TOO_LARGE, WL_ERROR);
  347.         fclose(fp);
  348.         png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
  349.         return false;
  350.     }
  351.  
  352.     if (maps_ptr != nullptr) {
  353.         openttd::bitmaps8_t &maps = *maps_ptr;
  354.         maps.reserve(channels);
  355.         maps.resize(channels);
  356.         for (int i = 0; i < maps.size(); i++) {
  357.             maps[i].reserve(width * height);
  358.             maps[i].resize(width * height);
  359.         }
  360.         ReadHeightmapPNGImageData(maps, png_ptr, info_ptr);
  361.     }
  362.  
  363.     *x = width;
  364.     *y = height;
  365.  
  366.     fclose(fp);
  367.     png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
  368.     return true;
  369. }
  370.  
  371. #endif /* WITH_PNG */
  372.  
  373.  
  374. /**
  375.  * The BMP Heightmap loader.
  376.  */
  377. static void ReadHeightmapBMPImageData(openttd::bitmaps8_t &maps, BmpInfo *info, BmpData *data)
  378. {
  379.     uint x, y;
  380.     byte gray_palette[256];
  381.  
  382.     assert(maps.size() > 0);
  383.  
  384.     if (data->palette != nullptr) {
  385.         uint i;
  386.         bool all_gray = true;
  387.  
  388.         if (info->palette_size != 2) {
  389.             for (i = 0; i < info->palette_size && (info->palette_size != 16 || all_gray); i++) {
  390.                 all_gray &= data->palette[i].r == data->palette[i].g && data->palette[i].r == data->palette[i].b;
  391.                 gray_palette[i] = RGBToGrayscale(data->palette[i].r, data->palette[i].g, data->palette[i].b);
  392.             }
  393.  
  394.             /**
  395.              * For a non-gray palette of size 16 we assume that
  396.              * the order of the palette determines the height;
  397.              * the first entry is the sea (level 0), the second one
  398.              * level 1, etc.
  399.              */
  400.             if (info->palette_size == 16 && !all_gray) {
  401.                 for (i = 0; i < info->palette_size; i++) {
  402.                     gray_palette[i] = 256 * i / info->palette_size;
  403.                 }
  404.             }
  405.         } else {
  406.             /**
  407.              * For a palette of size 2 we assume that the order of the palette determines the height;
  408.              * the first entry is the sea (level 0), the second one is the land (level 1)
  409.              */
  410.             gray_palette[0] = 0;
  411.             gray_palette[1] = 16;
  412.         }
  413.     }
  414.  
  415.     /* Read the raw image data and convert in 8-bit grayscale */
  416.     for (y = 0; y < info->height; y++) {
  417.         byte *pixel = &maps[0][y * info->width];
  418.         byte *bitmap = &data->bitmap[y * info->width * (info->bpp == 24 ? 3 : 1)];
  419.  
  420.         if (info->bpp == 24) {
  421.             for (x = 0; x < info->width; x++) {
  422.                 *pixel = RGBToGrayscale(*bitmap, *(bitmap + 1), *(bitmap + 2));
  423.                 pixel++;
  424.                 bitmap += 3;
  425.             }
  426.         } else if (info->bpp == 8) {
  427.             for (x = 0; x < info->width; x++) {
  428.                 *pixel = gray_palette[*bitmap];
  429.                 pixel++;
  430.                 bitmap++;
  431.             }
  432.         } else {
  433.             // no implementation for other (4-bit, ...) bitmaps
  434.             assert(false);
  435.         }
  436.     }
  437. }
  438.  
  439. /**
  440.  * Reads the heightmap and/or size of the heightmap from a BMP file.
  441.  * If maps_array == nullptr only the size of the BMP is read, otherwise a map
  442.  * with grayscale pixels is allocated and assigned to each element of maps_array[maps].
  443.  */
  444. static bool ReadHeightmapBMP(const char *filename, uint *x, uint *y, openttd::bitmaps8_t *maps_ptr)
  445. {
  446.     FILE *f;
  447.     BmpInfo info;
  448.     BmpData data;
  449.     BmpBuffer buffer;
  450.  
  451.     /* Init BmpData */
  452.     memset(&data, 0, sizeof(data));
  453.  
  454.     f = FioFOpenFile(filename, "rb", HEIGHTMAP_DIR);
  455.     if (f == nullptr) {
  456.         ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_PNGMAP_FILE_NOT_FOUND, WL_ERROR);
  457.         return false;
  458.     }
  459.  
  460.     BmpInitializeBuffer(&buffer, f);
  461.  
  462.     if (!BmpReadHeader(&buffer, &info, &data)) {
  463.         ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_BMPMAP_IMAGE_TYPE, WL_ERROR);
  464.         fclose(f);
  465.         BmpDestroyData(&data);
  466.         return false;
  467.     }
  468.  
  469.     /* Check if image dimensions don't overflow a size_t to avoid memory corruption. */
  470.     if ((uint64)info.width * info.height >= (size_t)-1 / (info.bpp == 24 ? 3 : 1)) {
  471.         ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_HEIGHTMAP_TOO_LARGE, WL_ERROR);
  472.         fclose(f);
  473.         BmpDestroyData(&data);
  474.         return false;
  475.     }
  476.  
  477.     if (maps_ptr != nullptr) {
  478.         if (!BmpReadBitmap(&buffer, &info, &data)) {
  479.             ShowErrorMessage(STR_ERROR_BMPMAP, STR_ERROR_BMPMAP_IMAGE_TYPE, WL_ERROR);
  480.             fclose(f);
  481.             BmpDestroyData(&data);
  482.             return false;
  483.         }
  484.  
  485.         openttd::bitmaps8_t &maps = *maps_ptr;
  486.         // rgb
  487.         maps.reserve(3);
  488.         maps.resize(3);
  489.         for (int i = 0; i < maps.size(); i++) {
  490.             maps[i].reserve(info.width * info.height);
  491.             maps[i].resize(info.width * info.height);
  492.         }
  493.         ReadHeightmapBMPImageData(maps, &info, &data);
  494.     }
  495.  
  496.     BmpDestroyData(&data);
  497.  
  498.     *x = info.width;
  499.     *y = info.height;
  500.  
  501.     fclose(f);
  502.     return true;
  503. }
  504.  
  505. #include "tree_map.h"
  506.  
  507. static bool CanPlantTreesOnTile(TileIndex tile, bool allow_desert)
  508. {
  509.     switch (GetTileType(tile)) {
  510.         case MP_WATER:
  511.             return !IsBridgeAbove(tile) && IsCoast(tile) && !IsSlopeWithOneCornerRaised(GetTileSlope(tile));
  512.  
  513.         case MP_CLEAR:
  514.             return !IsBridgeAbove(tile) && !IsClearGround(tile, CLEAR_FIELDS) && GetRawClearGround(tile) != CLEAR_ROCKS &&
  515.                    (allow_desert || !IsClearGround(tile, CLEAR_DESERT));
  516.  
  517.         default: return false;
  518.     }
  519. }
  520.  
  521. // generate number 0 to max_value
  522. std::uint8_t randr(const std::uint8_t max_value)
  523. {
  524.     const std::uint8_t rng = rand() & 255;
  525.     return (rng * max_value + 127) >> 8;
  526. }
  527.  
  528. static TreeType MakeTreeType(TileIndex tile, uint height, uint moisture)
  529. {
  530.     TreeType type = TREE_INVALID;
  531.  
  532.     switch (_settings_game.game_creation.landscape) {
  533.         case LT_TEMPERATE:
  534.             type = TreeType(TREE_TEMPERATE + (height * TREE_COUNT_TEMPERATE) / 256);
  535.             break;
  536.  
  537.         case LT_ARCTIC:
  538.             //type = TreeType(TREE_SUB_ARCTIC + (mapsize.y * TREE_COUNT_SUB_ARCTIC) / 256);
  539.             if (height < 128 && randr(3) == 0) {
  540.                 // mixed leafy
  541.                 if (moisture >= 192) {
  542.                     // light green
  543.                     type = TreeType(TREE_SUB_ARCTIC + 7);
  544.                 } else if (moisture >= 128) {
  545.                     // green
  546.                     type = TreeType(TREE_SUB_ARCTIC + 3);
  547.                 } else if (moisture >= 64) {
  548.                     // red
  549.                     type = TreeType(TREE_SUB_ARCTIC + (randr(1) ? 4 : 6));
  550.                 } else {
  551.                     // yellow
  552.                     type = TreeType(TREE_SUB_ARCTIC + 5);
  553.                 }
  554.             } else {
  555.                 // conifer only
  556.                 // types 2 and 3
  557.                 if (moisture >= 170) {
  558.                     type = TreeType(TREE_SUB_ARCTIC + 0);
  559.                 } else if (moisture >= 85) {
  560.                     type = TreeType(TREE_SUB_ARCTIC + 1);
  561.                 } else {
  562.                     type = TreeType(TREE_SUB_ARCTIC + 2);
  563.                 }
  564.             }
  565.             break;
  566.  
  567.         case LT_TROPIC:
  568.             switch (GetTropicZone(tile)) {
  569.                 case TROPICZONE_NORMAL:
  570.                     type = TreeType(TREE_SUB_TROPICAL + (height * TREE_COUNT_SUB_TROPICAL) / 256);
  571.                     break;
  572.                 case TROPICZONE_DESERT:
  573.                     type = TREE_CACTUS;
  574.                     break;
  575.                 case TROPICZONE_RAINFOREST:
  576.                     type = TreeType(TREE_RAINFOREST + (height * TREE_COUNT_RAINFOREST) / 256);
  577.                     break;
  578.             }
  579.             break;
  580.  
  581.         case LT_TOYLAND:
  582.             type = TreeType(TREE_TOYLAND + (height * TREE_COUNT_TOYLAND) / 256);
  583.             break;
  584.     }
  585.     return type;
  586. }
  587.  
  588. /**
  589.  * This function takes care of the fact that land in OpenTTD can never differ
  590.  * more than 1 in mapsize.y
  591.  */
  592. void FixSlopes()
  593. {
  594.     uint width, height;
  595.     int row, col;
  596.     byte current_tile;
  597.  
  598.     /* Adjust height difference to maximum one horizontal/vertical change. */
  599.     width   = MapSizeX();
  600.     height  = MapSizeY();
  601.  
  602.     /* Top and left edge */
  603.     for (row = 0; (uint)row < height; row++) {
  604.         for (col = 0; (uint)col < width; col++) {
  605.             current_tile = MAX_TILE_HEIGHT;
  606.             if (col != 0) {
  607.                 /* Find lowest tile; either the top or left one */
  608.                 current_tile = TileHeight(TileXY(col - 1, row)); // top edge
  609.             }
  610.             if (row != 0) {
  611.                 if (TileHeight(TileXY(col, row - 1)) < current_tile) {
  612.                     current_tile = TileHeight(TileXY(col, row - 1)); // left edge
  613.                 }
  614.             }
  615.  
  616.             /* Does the height differ more than one? */
  617.             if (TileHeight(TileXY(col, row)) >= (uint)current_tile + 2) {
  618.                 /* Then change the height to be no more than one */
  619.                 SetTileHeight(TileXY(col, row), current_tile + 1);
  620.             }
  621.         }
  622.     }
  623.  
  624.     /* Bottom and right edge */
  625.     for (row = height - 1; row >= 0; row--) {
  626.         for (col = width - 1; col >= 0; col--) {
  627.             current_tile = MAX_TILE_HEIGHT;
  628.             if ((uint)col != width - 1) {
  629.                 /* Find lowest tile; either the bottom and right one */
  630.                 current_tile = TileHeight(TileXY(col + 1, row)); // bottom edge
  631.             }
  632.  
  633.             if ((uint)row != height - 1) {
  634.                 if (TileHeight(TileXY(col, row + 1)) < current_tile) {
  635.                     current_tile = TileHeight(TileXY(col, row + 1)); // right edge
  636.                 }
  637.             }
  638.  
  639.             /* Does the height differ more than one? */
  640.             if (TileHeight(TileXY(col, row)) >= (uint)current_tile + 2) {
  641.                 /* Then change the height to be no more than one */
  642.                 SetTileHeight(TileXY(col, row), current_tile + 1);
  643.             }
  644.         }
  645.     }
  646. }
  647.  
  648. bool IsTileValidRiverSlope(TileIndex tile)
  649. {
  650.     int z;
  651.     Slope slope = GetTileSlope(tile, &z);
  652.     return slope == SLOPE_FLAT || GetInclinedSlopeDirection(slope) != INVALID_DIAGDIR;
  653. }
  654.  
  655. int skew(int fract, int div, int range, float x)
  656. {
  657.     return int(std::round(std::pow(float(fract) / float(div), x) * range));
  658. }
  659.  
  660. template <typename T>
  661. struct point_t
  662. {
  663.     using P = point_t<T>;
  664.  
  665.     T x;
  666.     T y;
  667.  
  668.     point_t() {}
  669.     point_t(T _x, T _y) { x = _x; y = _y; }
  670.     point_t(const point_t &p) { x = p.x; y = p.y; }
  671.  
  672.     template <class I> point_t(I _x, I _y) { x = T(_x); y = T(_y); }
  673.     template <class I> void operator()(I _x, I _y) { x = T(_x); y = T(_y); }
  674.     void operator=(const P &p) { x = p.x; y = p.y; }
  675.  
  676.     // basic operators
  677.     bool operator!=(const P &p) const { return (x != p.x || y != p.y); }
  678.     bool operator==(const P &p) const { return (x == p.x && y == p.y); }
  679.     template <class I> bool operator>(const point_t<I> &p) const { return (x > p.x && y > p.y); }
  680.     template <class I> bool operator<(const point_t<I> &p) const { return (x < p.x && y < p.y); }
  681.     template <class I> bool operator>=(const point_t<I> &p) const { return (x >= p.x && y >= p.y); }
  682.     template <class I> bool operator<=(const point_t<I> &p) const { return (x <= p.x && y <= p.y); }
  683.     P operator-() const { return P(-x, -y); }
  684.  
  685.     // point<I> operators
  686.     template <class I> P operator+(const point_t<I> &p) const { return P(x + p.x, y + p.y); }
  687.     template <class I> P operator-(const point_t<I> &p) const { return P(x - p.x, y - p.y); }
  688.     template <class I> P operator*(const point_t<I> &p) const { return P(x * p.x, y * p.y); }
  689.     template <class I> P operator/(const point_t<I> &p) const { return P(x / p.x, y / p.y); }
  690.  
  691.     template <class I> P &operator+=(const point_t<I> &p) { x += p.x; y += p.y; return *this; }
  692.     template <class I> P &operator-=(const point_t<I> &p) { x -= p.x; y -= p.y; return *this; }
  693.     template <class I> P &operator*=(const point_t<I> &p) { x *= p.x; y *= p.y; return *this; }
  694.     template <class I> P &operator/=(const point_t<I> &p) { x /= p.x; y /= p.y; return *this; }
  695.  
  696.     // scalar<I> operators
  697.     template <class I> P operator+(const I &v) const { return P(x + v, y + v); }
  698.     template <class I> P operator-(const I &v) const { return P(x - v, y - v); }
  699.     template <class I> P operator*(const I &v) const { return P(x * v, y * v); }
  700.     template <class I> P operator/(const I &v) const { return P(x / v, y / v); }
  701.  
  702.     template <class I> void operator+=(const I &v) { x += v; y += v; }
  703.     template <class I> void operator-=(const I &v) { x -= v; y -= v; }
  704.     template <class I> void operator*=(const I &v) { x *= v; y *= v; }
  705.     template <class I> void operator/=(const I &v) { x /= v; y /= v; }
  706.  
  707.     //
  708.     bool is_zero() const { return (x == T(0) && y == T(0)); }
  709. };
  710.  
  711. // points on a rectangle
  712. // 1 2 3
  713. // 4 5 6
  714. // 7 8 9
  715. enum class rect_origin_t
  716. {
  717.     left_top,
  718.     top,
  719.     right_top,
  720.  
  721.     left,
  722.     center,
  723.     right,
  724.  
  725.     left_bottom,
  726.     bottom,
  727.     right_bottom,
  728. };
  729.  
  730. template <typename T>
  731. struct rect_t
  732. {
  733.     T left;
  734.     T top;
  735.     T right;
  736.     T bottom;
  737.  
  738.     rect_t() {}  
  739.     rect_t(T width, T height) : left(0), top(0), right(width), bottom(height) {}
  740.     rect_t(const point_t<T> &p) : left(0), top(0), right(p.x), bottom(p.y) {}
  741.     rect_t(T _left, T _top, T _right, T _bottom) : left(_left), top(_top), right(_right), bottom(_bottom) {}
  742.     rect_t(const rect_t<T> &r) { copy_rect(r); }
  743.  
  744.     void copy_rect(const rect_t<T> &r)
  745.     {
  746.         left = r.left;
  747.         top = r.top;
  748.         right = r.right;
  749.         bottom = r.bottom;
  750.     }
  751.  
  752.     bool operator!=(const rect_t<T> &r) const { return (left != r.left || right != r.right || top != r.top || bottom != r.bottom); }
  753.     bool operator==(const rect_t<T> &r) const { return (left == r.left && right == r.right && top == r.top && bottom == r.bottom); }
  754.     void operator()(const T &l, const T &t, const T &r, const T &b) { (*this) = rect_t<T>(l,t,r,b); }
  755.     void operator()(const rect_t<T> &r) { (*this) = r; }
  756.  
  757.     const rect_t<T> &get_rect() { return *this; }
  758.  
  759.     T width() const { return right - left; }
  760.     T height() const { return bottom - top; }
  761.  
  762.     point_t<T> size() const { return point_t<T>(width(), height()); }
  763.  
  764.     point_t<T> lefttop() const { return point_t<T>(left,top); }
  765.     point_t<T> righttop() const { return point_t<T>(right,top); }
  766.     point_t<T> leftbottom() const { return point_t<T>(left,bottom); }
  767.     point_t<T> rightbottom() const { return point_t<T>(right,bottom); }
  768.  
  769.     point_t<T> lt() const { return point_t<T>(left,top); }
  770.     point_t<T> rt() const { return point_t<T>(right,top); }
  771.     point_t<T> lb() const { return point_t<T>(left,bottom); }
  772.     point_t<T> rb() const { return point_t<T>(right,bottom); }
  773.  
  774.     point_t<T> middle() const { return point_t<T>((left+right)/2, (top+bottom)/2); }
  775.  
  776.     // add offset required to "virtually" center where origin = (0, 0)
  777.     rect_t<T> centerh(const rect_t<T> &r) const { return rect_t<T>(r) + point((width() - r.width()) / 2, 0); }
  778.     rect_t<T> centerv(const rect_t<T> &r) const { return rect_t<T>(r) + point(0, (height() - r.height()) / 2); }
  779.     rect_t<T> center(const rect_t<T> &r) const { return rect_t<T>(r) + (size() - r.size()) / 2; }
  780.  
  781.     // center plus offset to real coordinates
  782.     rect_t<T> centero(const rect_t<T> &r) const { return rect_t<T>(r) + (size() - r.size()) / 2 + lefttop(); }
  783.  
  784.     rect_t<T> operator+(const point_t<T> &p) const { return rect_t<T>(left + p.x, top + p.y, right + p.x, bottom + p.y); }
  785.     rect_t<T> operator-(const point_t<T> &p) const { return rect_t<T>(left - p.x, top - p.y, right - p.x, bottom - p.y); }
  786.  
  787.     rect_t<T> operator+(const rect_t<T> &p) const { return rect_t<T>(left + p.left, top + p.top, right + p.right, bottom + p.bottom); }
  788.     rect_t<T> operator-(const rect_t<T> &p) const { return rect_t<T>(left - p.left, top - p.top, right - p.right, bottom - p.bottom); }
  789.  
  790.     rect_t<T> operator*(const int &n) const { return rect_t<T>(left * n, top * n, right * n, bottom * n); }
  791.     rect_t<T> operator/(const int &n) const { return rect_t<T>(left / n, top / n, right / n, bottom / n); }
  792.  
  793.     rect_t<T> operator/(const point_t<T> &p) const { return rect_t<T>(left / p.x, top / p.y, right / p.x, bottom / p.y); }
  794.  
  795.     rect_t<T> operator*(const float &n) const { return rect_t<T>(T(left * n), T(top * n), T(right * n), T(bottom * n)); }
  796.     rect_t<T> operator/(const float &n) const { return rect_t<T>(T(left / n), T(top / n), T(right / n), T(bottom / n)); }
  797.  
  798.     void move(T x, T y) { (*this) += point_t<T>(x - left, y - top); }
  799.  
  800.     bool is_valid_exclusive() const { return (left < right && top < bottom); }
  801.     bool is_valid_inclusive() const { return (left <= right && top <= bottom); }
  802.  
  803.     bool is_empty() const { return (right <= left || bottom <= top); }
  804.  
  805.     bool overlaps(const rect_t<T> &r) const { return (right >= r.left && left <= r.right && bottom >= r.top && top <= r.bottom); }
  806.     bool overlaps_exclusive(const rect_t<T> &r) const { return  (right >= r.left && left < r.right && bottom >= r.top && top < r.bottom); }
  807.  
  808.     bool contains(const rect_t<T> &r) const { return (contains(r.lt()) && contains(r.rb())); }
  809.     bool contains(const point_t<T> &p) const { return (p.x >= left && p.x <= right && p.y >= top && p.y <= bottom); }
  810.     bool contains_exclusive(const point_t<T> &p) const { return (p.x >= left && p.x < right && p.y >= top && p.y < bottom); }
  811.  
  812.     void operator+=(const point_t<T> &p)
  813.     {
  814.         left += p.x;
  815.         top += p.y;
  816.         right += p.x;
  817.         bottom += p.y;
  818.     }
  819.  
  820.     void operator-=(const point_t<T> &p)
  821.     {
  822.         left -= p.x;
  823.         top -= p.y;
  824.         right -= p.x;
  825.         bottom -= p.y;
  826.     }
  827.  
  828.     void operator+=(const rect_t<T> &r)
  829.     {
  830.         left   += r.left;
  831.         top    += r.top;
  832.         right  += r.right;
  833.         bottom += r.bottom;
  834.     }
  835.  
  836.     void operator-=(const rect_t<T> &r)
  837.     {
  838.         left   -= r.left;
  839.         top    -= r.top;
  840.         right  -= r.right;
  841.         bottom -= r.bottom;
  842.     }
  843.  
  844.     rect_t<T> inclusive_intersect(const rect_t<T> &r) const
  845.     {
  846.         return rect_t<T>((left > r.left ? left : r.left),
  847.             (top > r.top ? top : r.top),
  848.             (right < r.right ? right : r.right),
  849.             (bottom < r.bottom ? bottom : r.bottom));
  850.     }
  851.  
  852.     rect_t<T> exclusive_intersect(const rect_t<T> &r) const
  853.     {
  854.         return rect_t<T>((left > r.left ? left : r.left),
  855.             (top > r.top ? top : r.top),
  856.             (right < r.right ? right : r.right-1),
  857.             (bottom < r.bottom ? bottom : r.bottom-1));
  858.     }
  859.  
  860.     void clip_inclusive(const rect_t<T> &r)
  861.     {
  862.         left = _Mlimit(left, r.left, r.right);
  863.         top = _Mlimit(top, r.top, r.bottom);
  864.         right = _Mlimit(right, r.left, r.right);
  865.         bottom = _Mlimit(bottom, r.top, r.bottom);
  866.     }
  867.  
  868.     void clip_exclusive(const rect_t<T> &r)
  869.     {
  870.         left = _Mlimit(left, r.left, r.right-1);
  871.         top = _Mlimit(top, r.top, r.bottom-1);
  872.         right = _Mlimit(right, r.left, r.right-1);
  873.         bottom = _Mlimit(bottom, r.top, r.bottom-1);
  874.     }
  875.  
  876.     void expand(const rect_t<T> &r)
  877.     {
  878.         if (r.is_empty()) return;
  879.         if (left > r.left) left = r.left;
  880.         if (top > r.top) top = r.top;
  881.         if (right < r.right) right = r.right;
  882.         if (bottom < r.bottom) bottom = r.bottom;
  883.     }
  884.  
  885.     point_t<T> constrain(const rect_t<T> &r)
  886.     {
  887.         point_t<T> p(0,0);
  888.         if (left < r.left) p.x = r.left - left;
  889.         else if (right > r.right) p.x = r.right - right;
  890.         if (top < r.top) p.y = r.top - top;
  891.         else if (bottom > r.bottom) p.y = r.bottom - bottom;
  892.         return p;
  893.     }
  894. };
  895.  
  896. // height-mapping variables and coordinate scaling and translation
  897. struct map_t
  898. {
  899.     using P = point_t<uint>;
  900.  
  901.     map_t(const P &img) : num_div(16384), scale(0)
  902.     {
  903.         size.x = 0;
  904.         size.y = 0;
  905.  
  906.         // Get map size and calculate scale and padding values
  907.         switch (_settings_game.game_creation.heightmap_rotation) {
  908.             default: NOT_REACHED();
  909.             case HM_COUNTER_CLOCKWISE:
  910.                 size.x = MapSizeX();
  911.                 size.y = MapSizeY();
  912.                 break;
  913.             case HM_CLOCKWISE:
  914.                 size.x = MapSizeY();
  915.                 size.y = MapSizeX();
  916.                 break;
  917.         }
  918.  
  919.         padding.x = 0;
  920.         padding.y = 0;
  921.  
  922.         const P &diff = img - size;
  923.  
  924.         if ((img.x * num_div) / img.y > ((size.x * num_div) / size.y)) {
  925.             // Image is wider than map - center vertically
  926.             padding.x = (1 + size.y - ((img.y * scale) / num_div)) / 2;
  927.         }
  928.  
  929.         if ((img.y * num_div) / img.x > ((size.y * num_div) / size.x)) {
  930.             // Image is taller than map - center horizontally
  931.             padding.y = (1 + size.x - ((img.x * scale) / num_div)) / 2;
  932.         }
  933.  
  934.         // select a scale and padding to fit the map rectangle within the source heightmap
  935.         if (img.x < img.y) {
  936.             scale = (size.x * num_div) / img.x;
  937.         } else {
  938.             scale = (size.y * num_div) / img.y;
  939.         }
  940.  
  941.         printf("size(%i, %i) img(%i, %i) padding(%i, %i) scale(%i)\n", size.x, size.y, img.x, img.y, padding.x, padding.y, scale);
  942.     }
  943.  
  944.     bool is_padding(const P &p)
  945.     {
  946.         const uint add_pad = _settings_game.construction.freeform_edges ? 0 : 1;
  947.         return
  948.             p.x < padding.x || p.x >= (size.y - padding.x - add_pad) ||
  949.             p.y < padding.y || p.y >= (size.x  - padding.y - add_pad);
  950.     }
  951.  
  952.     // scale a point on the map to get source image coordinates
  953.     P get_image_offset(const P &map) const noexcept
  954.     {
  955.         P img;
  956.         // Use nearest neighbour resizing to scale map data
  957.         // rotate the map 45 degrees (counter)clockwise
  958.         img.x = (((map.x - padding.x) * num_div) / scale);
  959.         switch (_settings_game.game_creation.heightmap_rotation) {
  960.             default: NOT_REACHED();
  961.             case HM_COUNTER_CLOCKWISE: img.y = (((size.x - 1 - map.y - padding.y) * num_div) / scale); break;
  962.             case HM_CLOCKWISE: img.y = (((map.y - padding.y) * num_div) / scale); break;
  963.         }
  964.  
  965.         return img;
  966.     }
  967.  
  968.     TileIndex get_map_tile_index(const P &map) const noexcept
  969.     {
  970.         switch (_settings_game.game_creation.heightmap_rotation) {
  971.             default: NOT_REACHED();
  972.             case HM_COUNTER_CLOCKWISE: return TileXY(map.y, map.x);
  973.             case HM_CLOCKWISE:         return TileXY(map.x, map.y);
  974.         }
  975.  
  976.         return -1;
  977.     }
  978.  
  979.     // fixed point divisor
  980.     // Defines the precision of the aspect ratio (to avoid floating point)
  981.     const uint num_div = 16384;
  982.     uint scale;
  983.     P size;
  984.     P padding;
  985. };
  986.  
  987. /**
  988.  * Converts a given grayscale map to something that fits in OTTD map system
  989.  * and create a map of that data.
  990.  * @param img_width  the with of the image in pixels/tiles
  991.  * @param img_height the mapsize.y of the image in pixels/tiles
  992.  * @param maps       the input maps
  993.  */
  994. static void GrayscaleToMapHeights(uint img_width, uint img_height, openttd::bitmaps8_t &maps)
  995. {
  996.     using P = map_t::P;
  997.     map_t map(P(img_width, img_height));
  998.  
  999.     if (_settings_game.construction.freeform_edges) {
  1000.         for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0));
  1001.         for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y));
  1002.     }
  1003.  
  1004.     /* Form the landscape */
  1005.     if (maps.size() >= 1)
  1006.     for (uint x = 0; x < map.size.y; x++) {
  1007.         for (uint y = 0; y < map.size.x; y++) {
  1008.             TileIndex tile = map.get_map_tile_index(P(x, y));
  1009.  
  1010.             /* Check if current tile is within the 1-pixel map edge or padding regions */
  1011.             if (map.is_padding(P(x, y)) ||
  1012.                 (!_settings_game.construction.freeform_edges && DistanceFromEdge(tile) <= 1)) {
  1013.                 SetTileHeight(tile, 0);
  1014.                 /* Only clear the tiles within the map area. */
  1015.                 if (IsInnerTile(tile)) {
  1016.                     MakeClear(tile, CLEAR_GRASS, 3);
  1017.                 }
  1018.             } else {
  1019.                 P img = map.get_image_offset(P(x, y));
  1020.                 assert(img.x >= 0 && img.x < img_height && img.y >= 0 && img.y < img_width);
  1021.  
  1022.                 // red = surface mapsize.y
  1023.                 const uint8 z = maps[0][img.x * img_width + img.y];
  1024.                 //if (z == 0) {
  1025.                     //SetTileHeight(tile, 0);
  1026.                 //} else {
  1027.                     // 0 is sea level.
  1028.                     // Other grey scales are scaled evenly to the available height levels > 0.
  1029.                     // (The coastline is independent from the number of height levels)
  1030.                     //const int scaled_height = 1 + (z - 1) * _settings_game.construction.max_heightlevel / 255;
  1031.                     //SetTileHeight(tile, limit_inclusive<uint8>(scaled_height, 1, _settings_game.construction.max_heightlevel));
  1032.                     SetTileHeight(tile, z);
  1033.                 //}
  1034.  
  1035.                 /* Only clear the tiles within the map area. */
  1036.                 if (IsInnerTile(tile)) {
  1037.                     MakeClear(tile, CLEAR_GRASS, 3);
  1038.                 }
  1039.             }
  1040.         }
  1041.     }
  1042.  
  1043.     if (maps.size() >= 2)
  1044.     for (uint x = 0; x < map.size.y; x++) {
  1045.         for (uint y = 0; y < map.size.x; y++) {
  1046.             TileIndex tile = map.get_map_tile_index(P(x, y));
  1047.  
  1048.             /* Check if current tile is within the 1-pixel map edge or padding regions */
  1049.             if (map.is_padding(P(x, y)) ||
  1050.                 (!_settings_game.construction.freeform_edges && DistanceFromEdge(tile) <= 1)) {
  1051.                 continue;
  1052.             } else {
  1053.                 P img = map.get_image_offset(P(x, y));
  1054.                 assert(img.x >= 0 && img.x < img_height && img.y >= 0 && img.y < img_width);
  1055.  
  1056.                 const uint32 rng = Random();
  1057.                 // green = water availability
  1058.                 // forest or surface type and density
  1059.                 const int z = maps[0][img.x * img_width + img.y];
  1060.                 const int moisture = maps[1][img.x * img_width + img.y];
  1061.                 if (z == 0) {
  1062.                     // trees don't grow in the sea
  1063.                     continue;
  1064.                 }
  1065.  
  1066.                 // plant trees proportionate to moisture level
  1067.                 struct forest_density_t
  1068.                 {
  1069.                     // minimum moisture level
  1070.                     int moisture;
  1071.                     // odds the tile is filled
  1072.                     int odds;
  1073.                     // minimum number of trees
  1074.                     int trees;
  1075.                     // additional trees to add
  1076.                     int add_trees;
  1077.                 };
  1078.  
  1079.                 // power to skew distribution
  1080.                 const float sk = 3.0f;
  1081.  
  1082.                 const forest_density_t fmap[] =
  1083.                 {
  1084.                     // dry       = stone, desert, sand & gravel bars
  1085.                     {0, 0, 0, 0},
  1086.                     // arid      = dry grass and scrubland, sparse arid shrubs
  1087.                     {skew(1, 8, 256, sk), 4, 1, 0},
  1088.                     // semi-arid = grassland, bushes and few trees
  1089.                     {skew(2, 8, 256, sk), 3, 1, 0},
  1090.                     // semi-damp = light semi-arid underbrush, sparse forest (1 tree)
  1091.                     {skew(3, 8, 256, sk), 2, 1, 0},
  1092.                     // damp      = dense underbrush, forest (1 to 2 trees)
  1093.                     {skew(4, 8, 256, sk), 1, 1, 1},
  1094.                     // moist     = mixed wetland, medium forest (2 to 4 trees)
  1095.                     {skew(5, 8, 256, sk), 0, 2, 2},
  1096.                     // full      = mixed wetland, dense forest (3 to 4 trees)
  1097.                     {skew(6, 8, 256, sk), 0, 3, 1},
  1098.                     // max       = mixed wetland, dense forest (4 trees)
  1099.                     {skew(7, 8, 256, sk), 0, 4, 0},
  1100.                     // end marker
  1101.                     {256, 0, 0, 0},
  1102.                 };
  1103.  
  1104.                 for (int i = 0; fmap[i].moisture < 256; i++)    {
  1105.                     if (moisture >= fmap[i].moisture && moisture < fmap[i + 1].moisture) {
  1106.                         const int trees = fmap[i].trees + randr(fmap[i].add_trees);
  1107.                         if (trees > 0 && randr(fmap[i].odds) == 0) {
  1108.                             if (!IsTileType(tile, MP_TREES) && CanPlantTreesOnTile(tile, true)) {
  1109.                                 MakeTree(tile, MakeTreeType(tile, z, moisture), trees - 1, randr(7),
  1110.                                     TreeGround::TREE_GROUND_GRASS, 3);
  1111.                             }
  1112.                         }
  1113.                         break;
  1114.                     }
  1115.                 }
  1116.             }
  1117.         }
  1118.     }
  1119.  
  1120.     if (maps.size() >= 3)
  1121.     for (uint x = 0; x < map.size.y; x++) {
  1122.         for (uint y = 0; y < map.size.x; y++) {
  1123.             TileIndex tile = map.get_map_tile_index(P(x, y));
  1124.  
  1125.             /* Check if current tile is within the 1-pixel map edge or padding regions */
  1126.             if (map.is_padding(P(x, y)) ||
  1127.                 (!_settings_game.construction.freeform_edges && DistanceFromEdge(tile) <= 1)) {
  1128.                 continue;
  1129.             } else {
  1130.                 P img = map.get_image_offset(P(x, y));
  1131.                 assert(img.x >= 0 && img.x < img_height && img.y >= 0 && img.y < img_width);
  1132.  
  1133.                 if (IsInnerTile(tile)) {
  1134.                     // blue = presence of dense surface water
  1135.                     // surface obstructions such as: wetlands, pools, lakes, rivers
  1136.                     uint surface_water = maps[2][img.x * img_width + img.y];
  1137.  
  1138.                     if (surface_water == 20) {
  1139.                         // ocean
  1140.                         // z should be 0 for all these tiles,
  1141.                         // but due to hight-mapping and slope-fixing routines
  1142.                         // this may not be true... so do nothing
  1143.                     } else {
  1144.                         // if not ocean, limit tile Z >= 1
  1145.                         // (since 0 = ocean, a zero height non-ocean tile is not possible)
  1146.                         SetTileHeight(tile, limit_inclusive<uint8>(TileHeight(tile), 1, _settings_game.construction.max_heightlevel));
  1147.  
  1148.                         if (surface_water == 40) {
  1149.                             // rivers
  1150.                             if (IsTileValidRiverSlope(tile)) {
  1151.                                 MakeRiver(tile, Random());
  1152.                             }
  1153.                         } else if (surface_water == 60) {
  1154.                             // lakes
  1155.                             // only apply to flat tiles, never slopes
  1156.                             if (IsTileFlat(tile)) {
  1157.                                 MakeRiver(tile, Random());
  1158.                             }
  1159.                         }
  1160.                     }
  1161.                 }
  1162.             }
  1163.         }
  1164.     }
  1165.  
  1166.     FixSlopes();
  1167.     MarkWholeScreenDirty();
  1168. }
  1169.  
  1170. /**
  1171.  * Reads the heightmap with the correct file reader.
  1172.  * @param dft Type of image file.
  1173.  * @param filename Name of the file to load.
  1174.  * @param[out] x Length of the image.
  1175.  * @param[out] y mapsize.y of the image.
  1176.  * @param[in,out] map If not \c nullptr, destination to store the loaded block of image data.
  1177.  * @return Whether loading was successful.
  1178.  */
  1179. static bool ReadHeightMap(DetailedFileType dft, const char *filename, uint *x, uint *y, openttd::bitmaps8_t *maps)
  1180. {
  1181.     switch (dft) {
  1182.         default:
  1183.             NOT_REACHED();
  1184.  
  1185. #ifdef WITH_PNG
  1186.         case DFT_HEIGHTMAP_PNG:
  1187.             return ReadHeightmapPNG(filename, x, y, maps);
  1188. #endif /* WITH_PNG */
  1189.  
  1190.         case DFT_HEIGHTMAP_BMP:
  1191.             return ReadHeightmapBMP(filename, x, y, maps);
  1192.     }
  1193. }
  1194.  
  1195. /**
  1196.  * Get the dimensions of a heightmap.
  1197.  * @param dft Type of image file.
  1198.  * @param filename to query
  1199.  * @param x dimension x
  1200.  * @param y dimension y
  1201.  * @return Returns false if loading of the image failed.
  1202.  */
  1203. bool GetHeightmapDimensions(DetailedFileType dft, const char *filename, uint *x, uint *y)
  1204. {
  1205.     return ReadHeightMap(dft, filename, x, y, nullptr);
  1206. }
  1207.  
  1208. /**
  1209.  * Load a heightmap from file and change the map in his current dimensions
  1210.  *  to a landscape representing the heightmap.
  1211.  * It converts pixels to mapsize.y. The brighter, the higher.
  1212.  * @param dft Type of image file.
  1213.  * @param filename of the heightmap file to be imported
  1214.  */
  1215. void LoadHeightmap(DetailedFileType dft, const char *filename)
  1216. {
  1217.     uint x, y;
  1218.     openttd::bitmaps8_t maps;
  1219.  
  1220.     if (!ReadHeightMap(dft, filename, &x, &y, &maps)) {
  1221.         return;
  1222.     }
  1223.     GrayscaleToMapHeights(x, y, maps);
  1224.     maps.clear();
  1225. }
  1226.  
  1227. /**
  1228.  * Make an empty world where all tiles are of mapsize.y 'tile_height'.
  1229.  * @param tile_height of the desired new empty world
  1230.  */
  1231. void FlatEmptyWorld(byte tile_height)
  1232. {
  1233.     int edge_distance = _settings_game.construction.freeform_edges ? 0 : 2;
  1234.     for (uint row = edge_distance; row < MapSizeY() - edge_distance; row++) {
  1235.         for (uint col = edge_distance; col < MapSizeX() - edge_distance; col++) {
  1236.             SetTileHeight(TileXY(col, row), tile_height);
  1237.         }
  1238.     }
  1239.  
  1240.     FixSlopes();
  1241.     MarkWholeScreenDirty();
  1242. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top