281 lines
8.6 KiB
C++
281 lines
8.6 KiB
C++
// Heightmap.h: interface for the CHeightmap class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#if !defined(AFX_HEIGHTMAP_H__F92AE690_FC38_4249_BEA9_51384504DF9E__INCLUDED_)
|
|
#define AFX_HEIGHTMAP_H__F92AE690_FC38_4249_BEA9_51384504DF9E__INCLUDED_
|
|
|
|
#if _MSC_VER > 1000
|
|
#pragma once
|
|
#endif // _MSC_VER > 1000
|
|
|
|
// Heightmap data type
|
|
typedef float t_hmap;
|
|
|
|
#define NUM_SECTORS 32 //!< Sector table dimensions (32*32)
|
|
|
|
// From Engine.
|
|
//! Surface type mask, masks bits resereved to store surface id.
|
|
#define SURFACE_TYPE_MASK (1|2|4)
|
|
//! Lighting bit, if not set this terrain pixel is considered in shadow.
|
|
#define TERRAIN_LIGHT_BIT 8
|
|
#define TERRAIN_BURNOUT_BIT 8
|
|
//! Heigtmap bitmask, masks all bits out of heightmap data reserved for special use.
|
|
#define TERRAIN_BITMASK (SURFACE_TYPE_MASK|TERRAIN_LIGHT_BIT)
|
|
|
|
enum EHeighmapInfo
|
|
{
|
|
//! Hole flag in heighmap info.
|
|
HEIGHTMAP_INFO_HOLE = 0x01,
|
|
//! Light flag in heighmap info.
|
|
HEIGHTMAP_INFO_LIGHT = 0x02,
|
|
};
|
|
|
|
//! Surface id mask in heighmap info.
|
|
#define HEIGHTMAP_INFO_SFTYPE_MASK (0x04|0x08|0x010)
|
|
//! Surface id shift in heighmap info.
|
|
#define HEIGHTMAP_INFO_SFTYPE_SHIFT 2
|
|
|
|
class CXmlArchive;
|
|
class CDynamicArray2D;
|
|
struct SNoiseParams;
|
|
class CVegetationMap;
|
|
class CTerrainGrid;
|
|
|
|
struct SSectorInfo
|
|
{
|
|
//! Size of terrain unit.
|
|
int unitSize;
|
|
//! Sector size in meters.
|
|
int sectorSize;
|
|
//! Size of texture for one sector in pixels.
|
|
int sectorTexSize;
|
|
//! Number of sectors on one side of terrain.
|
|
int numSectors;
|
|
//! Size of whole terrain surface texture.
|
|
int surfaceTextureSize;
|
|
};
|
|
|
|
/** Heightmap info.
|
|
*/
|
|
class CHeightmap
|
|
{
|
|
public:
|
|
// Construcktion / destrucktion
|
|
CHeightmap();
|
|
virtual ~CHeightmap();
|
|
|
|
// Member data access
|
|
uint GetWidth() { return m_iWidth; };
|
|
uint GetHeight() { return m_iHeight; };
|
|
|
|
//! Get size of every heightmap unit in meters.
|
|
int GetUnitSize() const { return m_unitSize; };
|
|
|
|
//! Convert from world coordinates to heightmap coordinates.
|
|
CPoint WorldToHmap( const Vec3 &wp );
|
|
//! Convert from heightmap coordinates to world coordinates.
|
|
Vec3 HmapToWorld( CPoint hpos );
|
|
|
|
//! Get access to vegetation map.
|
|
CVegetationMap* GetVegetationMap();
|
|
|
|
//! Set size of current surface texture.
|
|
void SetSurfaceTextureSize( int width,int height );
|
|
|
|
//! Returns information about sectors on terrain.
|
|
//! @param si Structure filled with quered data.
|
|
void GetSectorsInfo( SSectorInfo &si );
|
|
|
|
t_hmap* GetData() { return m_pHeightmap; };
|
|
bool GetDataEx(t_hmap *pData, UINT iDestWidth, bool bSmooth = true, bool bNoise = true);
|
|
|
|
//! Fill image data.
|
|
//! @param resolution Resolution of needed heightmap.
|
|
//! @rect trgRect Target rectangle in scaled heightmap.
|
|
//! @param image, preallocated image of same size as srcRect where heightmap data will be stored.
|
|
bool GetData( CRect &trgRect,CFloatImage &hmap, bool bSmooth=true,bool bNoise=true );
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Terrain Grid functions.
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CTerrainGrid* GetTerrainGrid() const { return m_terrainGrid; };
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void SetXY( uint x,uint y,t_hmap iVal ) { m_pHeightmap[x + y*m_iWidth] = iVal; };
|
|
t_hmap& GetXY( uint x,uint y ) { return m_pHeightmap[x + y*m_iWidth]; };
|
|
t_hmap GetXY( uint x,uint y ) const { return m_pHeightmap[x + y*m_iWidth]; };
|
|
|
|
//! Calculate heightmap slope at givven point.
|
|
//! @return clamped to 0-255 range slope value.
|
|
float GetSlope( int x,int y );
|
|
|
|
bool GetPreviewBitmap( DWORD *pBitmapData,int width,bool bSmooth = true, bool bNoise = true);
|
|
|
|
unsigned char& InfoAt( int x,int y ) { return m_info.ValueAt(x,y); };
|
|
const unsigned char& InfoAt( int x,int y ) const { return m_info.ValueAt(x,y); };
|
|
unsigned char* GetInfoData() { return m_info.GetData(); };
|
|
|
|
// Hold / fetch
|
|
void Fetch();
|
|
void Hold();
|
|
bool Read(CString strFileName);
|
|
|
|
// (Re)Allocate / deallocate
|
|
void Resize( int iWidth, int iHeight,int unitSize,bool bCleanOld=true );
|
|
void CleanUp();
|
|
|
|
void InvalidateLayers();
|
|
|
|
// Importing / exporting
|
|
void Serialize( CXmlArchive &xmlAr,bool bSerializeVegetation );
|
|
void SerializeVegetation( CXmlArchive &xmlAr );
|
|
void SaveImage( LPCSTR pszFileName, bool bNoiseAndFilter = true);
|
|
void LoadBMP( LPCSTR pszFileName, bool bNoiseAndFilter = true);
|
|
|
|
//! Save heightmap to PGM file format.
|
|
void SavePGM( const CString &pgmFile );
|
|
//! Load heightmap from PGM file format.
|
|
void LoadPGM( const CString &pgmFile );
|
|
|
|
//! Save heightmap in RAW format.
|
|
void SaveRAW( const CString &rawFile );
|
|
//! Load heightmap from RAW format.
|
|
void LoadRAW( const CString &rawFile );
|
|
|
|
// Actions
|
|
void Smooth();
|
|
void Smooth( CFloatImage &hmap,const CRect &rect );
|
|
|
|
void Noise();
|
|
void Normalize();
|
|
void RemoveWater();
|
|
void Invert();
|
|
void MakeIsle();
|
|
void SmoothSlope();
|
|
void Randomize();
|
|
void MakeBeaches();
|
|
void LowerRange(float fFactor);
|
|
void Flatten(float fFactor);
|
|
void GenerateTerrain(const SNoiseParams &sParam);
|
|
void Clear();
|
|
|
|
//! Calculate surface type in rectangle.
|
|
//! @param rect if Rectangle is null surface type calculated for whole heightmap.
|
|
void CalcSurfaceTypes( const CRect *rect = NULL );
|
|
void SetLightingBit( CBitArray &lightbits,int w,int h );
|
|
void ClearLightingBit();
|
|
|
|
// Drawing
|
|
void DrawSpot(unsigned long iX, unsigned long iY,
|
|
uint8 iWidth, float fAddVal, float fSetToHeight = -1.0f,
|
|
bool bAddNoise = false);
|
|
|
|
void DrawSpot2( int iX, int iY, int radius,float insideRadius, float fHeigh,float fHardness=1.0f,bool bAddNoise = false,float noiseFreq=1,float noiseScale=1 );
|
|
void SmoothSpot( int iX, int iY, int radius, float fHeigh,float fHardness );
|
|
void RiseLowerSpot( int iX, int iY, int radius,float insideRadius, float fHeigh,float fHardness=1.0f,bool bAddNoise = false,float noiseFreq=1,float noiseScale=1 );
|
|
|
|
//! Make hole in the terrain.
|
|
void MakeHole( int x1,int y1,int width,int height,bool bMake );
|
|
|
|
//! Export terrain block.
|
|
void ExportBlock( const CRect &rect,CXmlArchive &ar );
|
|
//! Import terrain block, return offset of block to new position.
|
|
CPoint ImportBlock( CXmlArchive &ar,CPoint newPos,bool bUseNewPos=true );
|
|
|
|
//! Update terrain block in engine terrain.
|
|
void UpdateEngineTerrain( int x1,int y1,int width,int height,bool bElevation,bool bInfoBits );
|
|
//! Update all engine terrain.
|
|
void UpdateEngineTerrain( bool bOnlyElevation=true );
|
|
|
|
//! Synchronize engine hole bit with bit stored in editor heightmap.
|
|
void UpdateEngineHole( int x1,int y1,int width,int height );
|
|
|
|
void SetWaterLevel( float waterLevel );
|
|
float GetWaterLevel() const { return m_fWaterLevel; };
|
|
|
|
void CopyData(t_hmap *pDataOut)
|
|
{
|
|
memcpy(pDataOut, m_pHeightmap, sizeof(t_hmap) * m_iWidth * m_iHeight);
|
|
};
|
|
|
|
//! Copy from different heightmap data.
|
|
void CopyFrom( t_hmap *pHmap,unsigned char *pInfo,int resolution );
|
|
|
|
//! Dump to log sizes of all layers.
|
|
//! @return Total size allocated for layers.
|
|
int LogLayerSizes();
|
|
|
|
protected:
|
|
|
|
// Helper functionss
|
|
__inline void ClampToAverage(t_hmap *pValue, float fAverage);
|
|
__inline float ExpCurve(float v, float fCover, float fSharpness);
|
|
|
|
void SetModified();
|
|
|
|
// Verify internal class state
|
|
__inline void Verify()
|
|
{
|
|
ASSERT(m_iWidth && m_iHeight);
|
|
ASSERT(!IsBadWritePtr(m_pHeightmap, sizeof(t_hmap) * m_iWidth * m_iHeight));
|
|
};
|
|
|
|
// Initialization
|
|
void InitNoise();
|
|
|
|
private:
|
|
float m_fWaterLevel;
|
|
|
|
t_hmap *m_pHeightmap;
|
|
CDynamicArray2D *m_pNoise;
|
|
|
|
CByteImage m_info;
|
|
|
|
UINT m_iWidth;
|
|
UINT m_iHeight;
|
|
|
|
//! Size of surface texture.
|
|
int m_textureSize;
|
|
//! Number of sectors per grid side.
|
|
int m_numSectors;
|
|
int m_unitSize;
|
|
|
|
// When heightmap is rescaled to different size,its cached for faster future retrieval.
|
|
int m_cachedResolution;
|
|
CMemoryBlock m_cachedHeightmap;
|
|
|
|
//! Vegetation map for this heightmap.
|
|
CVegetationMap *m_vegetationMap;
|
|
|
|
//! Terrain grid.
|
|
CTerrainGrid* m_terrainGrid;
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Inlined implementation of get slope.
|
|
inline float CHeightmap::GetSlope( int x,int y )
|
|
{
|
|
//assert( x >= 0 && x < m_iWidth && y >= 0 && y < m_iHeight );
|
|
if (x <= 0 || y <= 0 || x >= m_iWidth-1 || y >= m_iHeight-1)
|
|
return 0;
|
|
|
|
t_hmap *p = &m_pHeightmap[x+y*m_iWidth];
|
|
float h = *p;
|
|
int w = m_iWidth;
|
|
float fs = (fabs(*(p+1) - h) +
|
|
fabs(*(p-1) - h) +
|
|
fabs(*(p+w) - h) +
|
|
fabs(*(p-w) - h) +
|
|
fabs(*(p+w+1) - h) +
|
|
fabs(*(p-w-1) - h) +
|
|
fabs(*(p+w-1) - h) +
|
|
fabs(*(p-w+1) - h));
|
|
fs = fs*8;
|
|
if (fs > 255.0f) fs = 255.0f;
|
|
return fs;
|
|
};
|
|
|
|
#endif // !defined(AFX_HEIGHTMAP_H__F92AE690_FC38_4249_BEA9_51384504DF9E__INCLUDED_)
|