/**
* Height map.
* The data structure is used at many places, it contains requirements from all its users.
* The tgp Perlin map generator is a more demanding user.
*/
struct HeightMap
{
HeightMap();
~HeightMap();
/** Fixed point type for heights, required by Perlin map generator tgp. */
typedef int16 height_t;
height_t *h; //< Array of heights (#size_x + 1) * (#size_y + 1).
/* (from tgp) Even though the sizes are always positive, there are many cases where
* X and Y need to be signed integers due to subtractions. */
uint dim_x; //< Line length #size_x + 1.
uint total_size; //< height map total size
uint map_size; //< Number of tiles in the map.
uint size_x; //< Size of the map in X direction.
uint size_y; //< Size of the map in Y direction.
uint log_x; //< 2log of #size_x.
uint log_y; //< 2log of #size_y.
/**
* Get the size of the map in X direction.
* @return The size of the map in X direction.
*/
inline int MapSizeX() const
{
return this->size_x;
}
/**
* Get the size of the map in Y direction.
* @return The size of the map in Y direction.
*/
inline int MapSizeY() const
{
return this->size_y;
}
/**
* Get the number of tiles in the map.
* @return Number of files in the map.
*/
inline int MapSize() const
{
return this->map_size;
}
/**
* Is the given coordinate valid as map coordinate?
* @param x X coordinate.
* @param y Y coordinate.
* @return Whether the indicated position in on the map.
*/
inline bool IsValidXY(int x, int y) const
{
return x >= 0 && x < (int)this->MapSizeX() && y >= 0 && y < (int)this->MapSizeY();
}
/**
* Get biggest coordinate of the map in X direction.
* @return The biggest coordinate of the map in X direction.
*/
inline int MapMaxX() const
{
return this->size_x - 1;
}
/**
* Get biggest coordinate of the map in Y direction.
* @return The biggest coordinate of the map in Y direction.
*/
inline int MapMaxY() const
{
return this->size_y - 1;
}
/**
* Get the number of bits needed for storing an X coordinate.
* @return Number of bits needed for storing an X coordinate.
*/
inline int MapLogX() const
{
return this->log_x;
}
/**
* Get the number of bits needed for storing an Y coordinate.
* @return Number of bits needed for storing an Y coordinate.
*/
inline int MapLogY() const
{
return this->log_y;
}
/**
* Scales the given value by the map size, where the given value is for a 256 by 256 map.
* @param n the value to scale.
* @return the scaled size.
*/
inline uint ScaleByMapSize(uint n) const
{
/* Subtract 12 from shift in order to prevent integer overflow
* for large values of n. It's safe since the min mapsize is 64x64. */
return CeilDiv(n << (this->MapLogX() + this->MapLogY() - 12), 1 << 4);
}
/**
* Height map access (both read and write).
* @param x X position.
* @param y Y position.
* @return height data.
*/
inline height_t &Height(uint x, uint y)
{
return this->h[x + y * this->dim_x];
}
/**
* Get height of the map at a given position.
* @param x X position.
* @param y Y position.
* @return height data.
*/
inline height_t Height(uint x, uint y) const
{
return this->h[x + y * this->dim_x];
}
void Setup(uint size_x, uint size_y, HeightMap::height_t initial_height);
void FixSlopes();
void CopyToGlobalMap();
};