File diff r23022:731ae1300799 → r23023:7b8669afd1db
src/heightmap.cpp
Show inline comments
 
@@ -356,168 +356,168 @@ static void GrayscaleToMapHeights(uint i
 
					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);
 
			}
 
		}
 
	}
 
}
 

	
 
/**
 
 * This function takes care of the fact that land in OpenTTD can never differ
 
 * more than 1 in height
 
 */
 
void FixSlopes()
 
{
 
	uint width, height;
 
	int row, col;
 
	byte current_tile;
 

	
 
	/* Adjust height difference to maximum one horizontal/vertical change. */
 
	width   = MapSizeX();
 
	height  = MapSizeY();
 

	
 
	/* Top and left edge */
 
	for (row = 0; (uint)row < height; row++) {
 
		for (col = 0; (uint)col < width; col++) {
 
			current_tile = MAX_TILE_HEIGHT;
 
			if (col != 0) {
 
				/* Find lowest tile; either the top or left one */
 
				current_tile = TileHeight(TileXY(col - 1, row)); // top edge
 
			}
 
			if (row != 0) {
 
				if (TileHeight(TileXY(col, row - 1)) < current_tile) {
 
					current_tile = TileHeight(TileXY(col, row - 1)); // left edge
 
				}
 
			}
 

	
 
			/* Does the height differ more than one? */
 
			if (TileHeight(TileXY(col, row)) >= (uint)current_tile + 2) {
 
				/* Then change the height to be no more than one */
 
				SetTileHeight(TileXY(col, row), current_tile + 1);
 
			}
 
		}
 
	}
 

	
 
	/* Bottom and right edge */
 
	for (row = height - 1; row >= 0; row--) {
 
		for (col = width - 1; col >= 0; col--) {
 
			current_tile = MAX_TILE_HEIGHT;
 
			if ((uint)col != width - 1) {
 
				/* Find lowest tile; either the bottom and right one */
 
				current_tile = TileHeight(TileXY(col + 1, row)); // bottom edge
 
			}
 

	
 
			if ((uint)row != height - 1) {
 
				if (TileHeight(TileXY(col, row + 1)) < current_tile) {
 
					current_tile = TileHeight(TileXY(col, row + 1)); // right edge
 
				}
 
			}
 

	
 
			/* Does the height differ more than one? */
 
			if (TileHeight(TileXY(col, row)) >= (uint)current_tile + 2) {
 
				/* Then change the height to be no more than one */
 
				SetTileHeight(TileXY(col, row), current_tile + 1);
 
			}
 
		}
 
	}
 
}
 

	
 
/**
 
 * Reads the heightmap with the correct file reader.
 
 * @param dft Type of image file.
 
 * @param filename Name of the file to load.
 
 * @param [out] x Length of the image.
 
 * @param [out] y Height of the image.
 
 * @param [inout] map If not \c NULL, destination to store the loaded block of image data.
 
 * @param[in,out] map If not \c NULL, destination to store the loaded block of image data.
 
 * @return Whether loading was successful.
 
 */
 
static bool ReadHeightMap(DetailedFileType dft, const char *filename, uint *x, uint *y, byte **map)
 
{
 
	switch (dft) {
 
		default:
 
			NOT_REACHED();
 

	
 
#ifdef WITH_PNG
 
		case DFT_HEIGHTMAP_PNG:
 
			return ReadHeightmapPNG(filename, x, y, map);
 
#endif /* WITH_PNG */
 

	
 
		case DFT_HEIGHTMAP_BMP:
 
			return ReadHeightmapBMP(filename, x, y, map);
 
	}
 
}
 

	
 
/**
 
 * Get the dimensions of a heightmap.
 
 * @param dft Type of image file.
 
 * @param filename to query
 
 * @param x dimension x
 
 * @param y dimension y
 
 * @return Returns false if loading of the image failed.
 
 */
 
bool GetHeightmapDimensions(DetailedFileType dft, const char *filename, uint *x, uint *y)
 
{
 
	return ReadHeightMap(dft, filename, x, y, NULL);
 
}
 

	
 
/**
 
 * Load a heightmap from file and change the map in his current dimensions
 
 *  to a landscape representing the heightmap.
 
 * It converts pixels to height. The brighter, the higher.
 
 * @param dft Type of image file.
 
 * @param filename of the heightmap file to be imported
 
 */
 
void LoadHeightmap(DetailedFileType dft, const char *filename)
 
{
 
	uint x, y;
 
	byte *map = NULL;
 

	
 
	if (!ReadHeightMap(dft, filename, &x, &y, &map)) {
 
		free(map);
 
		return;
 
	}
 

	
 
	GrayscaleToMapHeights(x, y, map);
 
	free(map);
 

	
 
	FixSlopes();
 
	MarkWholeScreenDirty();
 
}
 

	
 
/**
 
 * Make an empty world where all tiles are of height 'tile_height'.
 
 * @param tile_height of the desired new empty world
 
 */
 
void FlatEmptyWorld(byte tile_height)
 
{
 
	int edge_distance = _settings_game.construction.freeform_edges ? 0 : 2;
 
	for (uint row = edge_distance; row < MapSizeY() - edge_distance; row++) {
 
		for (uint col = edge_distance; col < MapSizeX() - edge_distance; col++) {
 
			SetTileHeight(TileXY(col, row), tile_height);
 
		}
 
	}
 

	
 
	FixSlopes();
 
	MarkWholeScreenDirty();
 
}