/** A small helper function to initialize the terrain */ static void TgenSetTileHeight(TileIndex tile, int height) { SetTileHeight(tile, height); /* Only clear the tiles within the map area. */ if (IsInnerTile(tile)) { MakeClear(tile, CLEAR_GRASS, 3); } }
/** * Return the slope of a given tile inside the map. * @param tile Tile to compute slope of * @param h If not \c NULL, pointer to storage of z height * @return Slope of the tile, except for the HALFTILE part */ Slope GetTileSlope(TileIndex tile, int *h) { assert(tile < MapSize()); if (!IsInnerTile(tile)) { if (h != NULL) *h = TileHeight(tile); return SLOPE_FLAT; } int hnorth = TileHeight(tile); // Height of the North corner. int hwest = TileHeight(tile + TileDiffXY(1, 0)); // Height of the West corner. int heast = TileHeight(tile + TileDiffXY(0, 1)); // Height of the East corner. int hsouth = TileHeight(tile + TileDiffXY(1, 1)); // Height of the South corner. return GetTileSlopeGivenHeight(hnorth, hwest, heast, hsouth, h); }
/** * Check if a given tile is flat * @param tile Tile to check * @param h If not \c NULL, pointer to storage of z height (only if tile is flat) * @return Whether the tile is flat */ bool IsTileFlat(TileIndex tile, int *h) { assert(tile < MapSize()); if (!IsInnerTile(tile)) { if (h != NULL) *h = TileHeight(tile); return true; } uint z = TileHeight(tile); if (TileHeight(tile + TileDiffXY(1, 0)) != z) return false; if (TileHeight(tile + TileDiffXY(0, 1)) != z) return false; if (TileHeight(tile + TileDiffXY(1, 1)) != z) return false; if (h != NULL) *h = z; return true; }
/** * Converts a given grayscale map to something that fits in OTTD map system * and create a map of that data. * @param img_width the with of the image in pixels/tiles * @param img_height the height of the image in pixels/tiles * @param map the input map */ static void GrayscaleToMapHeights(uint img_width, uint img_height, byte *map) { /* Defines the detail of the aspect ratio (to avoid doubles) */ const uint num_div = 16384; uint width, height; uint row, col; uint row_pad = 0, col_pad = 0; uint img_scale; uint img_row, img_col; TileIndex tile; /* Get map size and calculate scale and padding values */ switch (_settings_game.game_creation.heightmap_rotation) { default: NOT_REACHED(); case HM_COUNTER_CLOCKWISE: width = MapSizeX(); height = MapSizeY(); break; case HM_CLOCKWISE: width = MapSizeY(); height = MapSizeX(); break; } if ((img_width * num_div) / img_height > ((width * num_div) / height)) { /* Image is wider than map - center vertically */ img_scale = (width * num_div) / img_width; row_pad = (1 + height - ((img_height * img_scale) / num_div)) / 2; } else { /* Image is taller than map - center horizontally */ img_scale = (height * num_div) / img_height; col_pad = (1 + width - ((img_width * img_scale) / num_div)) / 2; } if (_settings_game.construction.freeform_edges) { for (uint x = 0; x < MapSizeX(); x++) MakeVoid(TileXY(x, 0)); for (uint y = 0; y < MapSizeY(); y++) MakeVoid(TileXY(0, y)); } /* Form the landscape */ for (row = 0; row < height; row++) { for (col = 0; col < width; col++) { switch (_settings_game.game_creation.heightmap_rotation) { default: NOT_REACHED(); case HM_COUNTER_CLOCKWISE: tile = TileXY(col, row); break; case HM_CLOCKWISE: tile = TileXY(row, col); break; } /* Check if current tile is within the 1-pixel map edge or padding regions */ if ((!_settings_game.construction.freeform_edges && DistanceFromEdge(tile) <= 1) || (row < row_pad) || (row >= (height - row_pad - (_settings_game.construction.freeform_edges ? 0 : 1))) || (col < col_pad) || (col >= (width - col_pad - (_settings_game.construction.freeform_edges ? 0 : 1)))) { SetTileHeight(tile, 0); } else { /* Use nearest neighbour resizing to scale map data. * We rotate the map 45 degrees (counter)clockwise */ img_row = (((row - row_pad) * num_div) / img_scale); switch (_settings_game.game_creation.heightmap_rotation) { default: NOT_REACHED(); case HM_COUNTER_CLOCKWISE: img_col = (((width - 1 - col - col_pad) * num_div) / img_scale); break; case HM_CLOCKWISE: img_col = (((col - col_pad) * num_div) / img_scale); break; } assert(img_row < img_height); assert(img_col < img_width); uint heightmap_height = map[img_row * img_width + img_col]; if (heightmap_height > 0) { /* 0 is sea level. * Other grey scales are scaled evenly to the available height levels > 0. * (The coastline is independent from the number of height levels) */ heightmap_height = 1 + (heightmap_height - 1) * _settings_game.construction.max_heightlevel / 255; } SetTileHeight(tile, heightmap_height); } /* Only clear the tiles within the map area. */ if (IsInnerTile(tile)) { MakeClear(tile, CLEAR_GRASS, 3); } } } }