/* ========================================================================== * ÀÛ ¼º ÀÚ : À̼ø±Ô * ÀÛ ¼º ÀÏ : 2006.12.04 * ³» ¿ë : ÁöÇü * ÁÖÀÇ»çÇ× : *===========================================================================*/ #pragma once #include "Shader.h" class cRay; class cSphere; class cBox; class cSceneNode; class cTerrainBranchNode; class cTerrainLeafNode; #ifdef MAP_EDITOR class cTerrainBuildingInfo; class cTerrainPaintingInfo; class cTerrainDetailingInfo; #endif /// MAP_EDITOR enum eTerrainViewMode; /// ÁöÇü »ó¼ö const unsigned int TERRAIN_DEFAULT_RESOLUTION = 512; const unsigned int TERRAIN_BUFF_CELL_COUNT = 128; const unsigned int TERRAIN_BUFF_LINE_COUNT = TERRAIN_BUFF_CELL_COUNT + 1; const unsigned int TERRAIN_BUFF_VERT_COUNT = TERRAIN_BUFF_LINE_COUNT * TERRAIN_BUFF_LINE_COUNT; const unsigned int TERRAIN_LEAF_CELL_COUNT = 8; const unsigned int TERRAIN_LEAF_LINE_COUNT = TERRAIN_LEAF_CELL_COUNT + 1; const unsigned int TERRAIN_LEAF_LINE_COUNT_X2 = TERRAIN_LEAF_LINE_COUNT * 2; const unsigned int TERRAIN_LEAF_VERT_COUNT = TERRAIN_LEAF_LINE_COUNT * TERRAIN_LEAF_LINE_COUNT; /// ÁöÇü ÅØ½ºÃ³ »ó¼ö const unsigned int TERRAIN_TEXTURE_COUNT = 21; const unsigned int TERRAIN_TEXTURE_COUNT_VER2 = 16; /// ÁöÇü ·Îµù ¿¡·¯ ÄÚµå const int TERRAIN_LOAD_ERROR_OPEN = -1; const int TERRAIN_LOAD_ERROR_FILE_HEADER = -2; const int TERRAIN_LOAD_ERROR_FILE_TYPE = -3; const int TERRAIN_LOAD_ERROR_FILE_VERSION = -4; const int TERRAIN_LOAD_ERROR_GRID_SIZE = -5; const int TERRAIN_LOAD_ERROR_TEXTURE_NAME = -6; const int TERRAIN_LOAD_ERROR_TEXTURE = -7; const int TERRAIN_LOAD_ERROR_NODE = -8; /// ÁöÇü Lod enum eTerrainLod { TERRAIN_LOD_0 = 0, TERRAIN_LOD_1, TERRAIN_LOD_2, TERRAIN_LOD_COUNT }; /// ÁöÇü ÆÄÀÏ Çì´õ #pragma pack( push, 1 ) class cTerrainFileHeader { public: /// ½Äº° ÄÚµå char mCode[12]; /// ¹öÀü unsigned int mVersion; /// ±×¸®µå Å©±â (¼¿ ¼ö) unsigned int mCellCount; /// Á¤Á¡´ç ¹ÌÅÍ ¼ö float mMetersPerVertex; /// ¹ÌÅÍ´ç ´ÜÀ§ ¼ö unsigned int mUnitsPerMeter; /// ÅØ½ºÃ³ ¼ö unsigned int mNumTextures; }; #pragma pack( pop ) /// ÁöÇü ÅØ½ºÃ³ class cTerrainTexture { friend class cTerrain; friend class cTerrainLeafNode; public: cTerrainTexture( unsigned int index, const cString& pathName, LPDIRECT3DTEXTURE9 tex ); ~cTerrainTexture(); void Grab(); void Drop(); const char* GetFileName() const; CBitmap* GetBitmap(); unsigned int GetWidth() const; unsigned int GetHeight() const; unsigned int GetIndexByTerrain() const; /// »ö»ó°ªÀ» ¸®ÅÏ /// ÁÖÀÇ: x¿Í y´Â [0, 1]»çÀÌÀÇ °ªÀ» °¡Á®¾ßÇÑ´Ù. bool GetColor( float* red, float* green, float* blue, float x, float y ); private: /// ÆÄÀÏ À̸§ cString mFileName; /// À̹ÌÁö µ¥ÀÌŸ cTargaImage mImageData; /// ºñÆ®¸Ê CBitmap mBitmap; /// ÁöÇü¿¡ ÀÇÇØ ¼³Á¤µÈ ³»ºÎ À妽º unsigned int mIndexByTerrain; /// ÂüÁ¶ Ä«¿îÆ® unsigned int mRefCount; private: /// DX9 LPDIRECT3DTEXTURE9 mTexture; }; inline const char* cTerrainTexture::GetFileName() const { return mFileName.Cstr(); } inline CBitmap* cTerrainTexture::GetBitmap() { return &mBitmap; } inline unsigned int cTerrainTexture::GetWidth() const { return mImageData.GetWidth(); } inline unsigned int cTerrainTexture::GetHeight() const { return mImageData.GetHeight(); } inline unsigned int cTerrainTexture::GetIndexByTerrain() const { return mIndexByTerrain; } /// ÁöÇü ¹öÆÛ class cTerrainBuffer { friend class cTerrain; friend class cTerrainLeafNode; public: cTerrainBuffer(); ~cTerrainBuffer(); bool Init( cTerrain* terrain, unsigned int xi, unsigned int yi ); protected: void UpdatePosCoord( cTerrain* terrain, unsigned int xstart, unsigned int ystart, unsigned int count ); void UpdateColor( cTerrain* terrain, unsigned int xstart, unsigned int ystart, unsigned int count ); void UpdateAlpha( cTerrain* terrain, unsigned int xstart, unsigned int ystart, unsigned int count ); private: unsigned int mXIndex; unsigned int mYIndex; /// DX9 LPDIRECT3DVERTEXBUFFER9 mPosCoordBuffer; LPDIRECT3DVERTEXBUFFER9 mNormalBuffer; LPDIRECT3DVERTEXBUFFER9 mColorBuffer; LPDIRECT3DVERTEXBUFFER9 mAlphaBuffer; }; /// ÁöÇü class cTerrain { static cTerrain* mSingleton; friend class cTerrainLeafNode; friend class cTerrainTexture; friend class cTerrainBuffer; #ifdef MAP_EDITOR friend class cTerrainBuilding; #endif public: cTerrain(); ~cTerrain(); /// Áö¿ò void Clear(); /// ÃʱâÈ­ void Init( unsigned int cellCount, float metersPerVertex = 1.0f, unsigned int unitsPerMeter = 100 ); bool IsInited() const; /// ·Îµù int Load( const cString& pathName ); #ifdef MAP_EDITOR bool LoadPaintAlpha( const cString& pathName, unsigned int numVerts ); #endif /// ó¸® void Process( bool testing ); /// ·»´õ¸µ void Render(); /// ÅØ½ºÃ³ bool LoadTexture( const cString& pathName ); bool LoadTexture( unsigned int index, const cString& pathName ); void UnLoadTexture( unsigned int index ); cTerrainTexture* GetTexture( int index ); /// ÇÈÅ· bool Pick( NiPoint3* pos, int mouseX, int mouseY ); bool Pick( NiPoint3* pos, const cRay& ray ); /// ±¸¿Í Ãæµ¹ÇÏ´Â ³ëµåµéÀ» ¼öÁý /// ¹Ù¿îµù ¹Ú½º·Î °Ë»çÇÑ´Ù. bool CollideSphere( tArray* pickedArray, const cSphere& sphere ); #ifdef MAP_EDITOR /// ºä ¸ðµå void SetViewMode( eTerrainViewMode viewMode ); /// ÀúÀå bool Save( const cString& pathName ); bool SavePaintAlpha( const cString& pathName ); /// ³ôÀÌ¸Ê void ClearHeightMap(); bool ImportHeightMap( const cString& pathName, float scale ); bool ImportHeightMap( const cString& pathName ); bool ExportHeightMap( const cString& pathName ); /// »ö»ó¸Ê void ClearColorMap(); bool ImportColorMap( const cString& pathName ); bool ExportColorMap( const cString& pathName ); /// ¾ËÆÄ¸Ê void ClearAlphaMap(); bool ImportAlphaMap( const cString& pathName ); bool ExportAlphaMap( const cString& pathName ); /// ½ºÄÉÀÏ void AdjustHeight( float scale ); /// ¸ÂÃã void SyncAllToNaviMesh(); /// ÆíÁý bool Raise( const NiPoint3& pos, float innerRadius, float outerRadius, float strength ); bool Lower( const NiPoint3& pos, float innerRadius, float outerRadius, float strength ); bool Flatten( const NiPoint3& pos, float innerRadius, float outerRadius, float strength ); bool Smooth( const NiPoint3& pos, float outerRadius, float ratio ); bool SyncToNaviMesh( const NiPoint3& pos, float innerRadius, float outerRadius ); bool SyncToPickHeight( const NiPoint3& pos, float innerRadius, float outerRadius, float z ); /// »öÄ¥ bool Color( const NiPoint3& pos, float innerRadius, float outerRadius, const NiColor& color ); bool Brush( const NiPoint3& pos, float innerRadius, float outerRadius, const NiColor& color, float opacity ); bool Lighter( const NiPoint3& pos, float innerRadius, float outerRadius ); bool Darker( const NiPoint3& pos, float innerRadius, float outerRadius ); bool BlurColor( const NiPoint3& pos, float outerRadius, float ratio ); /// µðÅ×ÀÏ void SetDetailTextures( cTerrainLeafNode* node, unsigned int index0, unsigned int index1, unsigned int index2 ); void SetDetailTexturesToAll( unsigned int index0, unsigned int index1, unsigned int index2 ); bool PaintAlpha( const NiPoint3& pos, float innerRadius, float outerRadius, const NiPoint3& alpha, bool applyDetailTex, unsigned int texIndex0, unsigned int texIndex1, unsigned int texIndex2 ); bool BlurAlpha( const NiPoint3& pos, float outerRadius, float ratio ); bool SharpenAlpha( const NiPoint3& pos, float outerRadius, float ratio ); /// º¯°æ ¿©ºÎ bool IsModified() const; #endif /// MAP_EDITOR /// Level of Detail void SetLodEnabled( bool enabled ); /// ÁÖº¯±¤ void SetAmbientLightAmbient( const NiColor& color ); void SetAmbientLightDiffuse( const NiColor& color ); void SetAmbientLightDimmer( float dimmer ); /// ¾È°³ void SetFog( bool enabled, const NiColor& color, float depth ); void SetFogColor( const NiColor& color ); void SetFogDepth( float depth ); /// ÁÖº¯±¤ NiAmbientLight* GetAmbientLight() const; /// ³ôÀ̰ª float GetHeight( float x, float y ) const; const float* GetHeights() const; /// ±×¸®µå Å©±â unsigned int GetCellCount() const; unsigned int GetLeafCellCount() const; /// ´ÜÀ§ float GetMetersPerVertex() const; unsigned int GetUnitsPerMeter() const; float GetUnitsPerVertex() const; float GetUnitsPerLeafNode() const; /// ÇØ´ç À§Ä¡ÀÇ ¸®ÇÁ ³ëµå cTerrainLeafNode* GetLeafNode( float x, float y ) const; /// ÇØ´ç À§Ä¡ÀÇ »ö»ó°ª bool GetColor( NiColor* color, const NiPoint3& pos ) const; /// ¸®ÇÁ ³ëµå ¹è¿­ tArray& GetLeafNodeArray(); /// º¸ÀÌ´Â ¸®ÇÁ ³ëµå ¼ö unsigned int GetNumVisibleNodes() const; /// ÁöÇü Àüü¸¦ °¨½Î´Â °æ°è »óÀÚ const cBox& GetBoundBox() const; /// ÁöÇüÀÇ ³ôÀ̰ª /// À妽º°¡ ¹üÀ§¸¦ ¹þ¾î³­ °æ¿ì false¸¦ ¸®ÅÏÇÑ´Ù. bool GetHeight( float* height, unsigned int xi, unsigned int yi ); /// NiFogProperty* GetFogProperty() const; protected: #ifdef MAP_EDITOR /// ¹é¾÷ /// Undo, Redo¿¡ ÇÊ¿äÇÑ Á¤º¸¸¦ ¼öÁýÇÑ´Ù. bool BackupBuilding( cTerrainBuildingInfo* info, unsigned int xbegin, unsigned int ybegin, unsigned int xend, unsigned int yend, const NiPoint3& pos, float outerRadius ); bool BackupPainting( cTerrainPaintingInfo* info, unsigned int xbegin, unsigned int ybegin, unsigned int xend, unsigned int yend, const NiPoint3& pos, float outerRadius ); bool BackupDetailing( cTerrainDetailingInfo* info, unsigned int xbegin, unsigned int ybegin, unsigned int xend, unsigned int yend, const NiPoint3& pos, float outerRadius ); /// °»½Å void UpdateBuilding( cTerrainBuildingInfo* info, unsigned int xbegin, unsigned int ybegin, unsigned int xend, unsigned int yend, const NiPoint3& pos, float outerRadius ); void UpdatePainting( cTerrainPaintingInfo* info, unsigned int xbegin, unsigned int ybegin, unsigned int xend, unsigned int yend, const NiPoint3& pos, float outerRadius ); void UpdateDetailing( cTerrainDetailingInfo* info, unsigned int xbegin, unsigned int ybegin, unsigned int xend, unsigned int yend, const NiPoint3& pos, float outerRadius ); #endif /// MAP_EDITOR void CreateIndexedBuffer(); /// ±×¸®µå Å©±â¸¦ °Ë»ç bool CheckCellCount( unsigned int cellCount ); /// ·»´õ¸µ void Render0( LPDIRECT3DDEVICE9 device, const D3DXMATRIX& worldViewProj ); void Render1( LPDIRECT3DDEVICE9 device, const D3DXMATRIX& worldViewProj ); /// ÅØ½ºÃ³ void AddTexture( unsigned int index, cTerrainTexture* tex ); void RemoveTexture( unsigned int index ); /// ¹öÆÛ cTerrainBuffer* GetBuffer( unsigned int xi, unsigned int yi ); /// Àû¿ë ¹üÀ§ °è»ê bool CalcRange( unsigned int* xbegin, unsigned int* ybegin, unsigned int* xend, unsigned int* yend, const NiPoint3& pos, float outerRadius ); bool CalcRangeTight( unsigned int* xbegin, unsigned int* ybegin, unsigned int* xend, unsigned int* yend, const NiPoint3& pos, float outerRadius ); /// ÇØ´ç À§Ä¡¿¡ ¸®ÇÁ ³ëµå¸¦ ¼³Á¤ void SetLeafNode( unsigned int xi, unsigned int yi, cTerrainLeafNode* node ); /// ³ôÀ̰ª void SetHeight( unsigned int xi, unsigned int yi, float height ); float GetHeightFast( unsigned int xi, unsigned int yi ) const; /// ¹ý¼±°ª void ComputeNormals( unsigned int xbegin, unsigned int ybegin, unsigned int xend, unsigned int yend ); const NiPoint3& GetNormalFast( unsigned int xi, unsigned int yi ) const; /// »ö»ó°ª void SetColor( unsigned int xi, unsigned int yi, const NiColor& color ); bool GetColor( NiColor* color, unsigned int xi, unsigned int yi ); const NiColor& GetColorFast( unsigned int xi, unsigned int yi ) const; /// ¾ËÆÄ°ª void SetAlpha( unsigned int xi, unsigned int yi, const NiPoint3& alpha ); bool GetAlpha( NiPoint3* alpha, unsigned int xi, unsigned int yi ); const NiPoint3& GetAlphaFast( unsigned int xi, unsigned int yi ) const; void SetPaintAlpha( unsigned int xi, unsigned int yi, const NiPoint3& alpha ); bool GetPaintAlpha( NiPoint3* alpha, unsigned int xi, unsigned int yi ); const NiPoint3& GetPaintAlphaFast( unsigned int xi, unsigned int yi ) const; unsigned int CalcLOD( float sqrDist ); public: /// ´ÜÀÏü¸¦ ¸®ÅÏ static cTerrain* GetSingleton(); protected: /// ÃʱâÈ­ ¿©ºÎ bool mInited; /// ±×¸®µå Å©±â unsigned int mCellCount; unsigned int mLineCount; /// Á¤Á¡´ç ¹ÌÅÍ ( 1 ) float mMetersPerVertex; /// ¹ÌÅÍ´ç ´ÜÀ§ ( 100 ) unsigned int mUnitsPerMeter; /// Á¤Á¡´ç ´ÜÀ§ float mUnitsPerVertex; /// ¸®ÇÁ ³ëµå´ç ´ÜÀ§ float mUnitsPerLeafNode; /// ·çÆ® ³ëµå cTerrainBranchNode* mRootNode; /// ¸®ÇÁ ³ëµå ¹è¿­ typedef tArray cLeafNodeArray; cLeafNodeArray mNodeArray; /// °¡½Ã ¹è¿­ cLeafNodeArray mVisibleArray; /// ³ôÀÌ ¹è¿­ float* mHeights; /// ¹ý¼± ¹è¿­ NiPoint3* mNormals; /// »ö»ó ¹è¿­ NiColor* mColors; /// ¾ËÆÄ ¹è¿­ NiPoint3* mAlphas; NiPoint3* mPaintAlphas; /// ÁÖº¯±¤ NiAmbientLightPtr mAmbientLight; /// °øÅë ·»´õ¸µ ¼Ó¼º NiFogPropertyPtr mFogProp; /// Level of detail bool mLodEnabled; float mSquaredDistanceLod[TERRAIN_LOD_COUNT]; /// ÅØ½ºÃ³ ¹è¿­ cTerrainTexture* mTextures[TERRAIN_TEXTURE_COUNT]; unsigned int mNumTextures; /// ÅØ½ºÃ³ ¸Ê typedef tHashMap cTextureMap; cTextureMap mTextureMap; /// ¼ÎÀÌ´õ cTerrainShader mShader0; cTerrainShader mShader1; /// ¹öÆÛ cTerrainBuffer** mBuffer; /// DX9 LPDIRECT3DVERTEXDECLARATION9 mVertexDeclaration0; LPDIRECT3DVERTEXDECLARATION9 mVertexDeclaration1; ////////////////////////////////////////////////////////////////////////// /// LOD index buffer Ãß°¡ /// 8x8 LOD-0 enum { eCRACK_LEFT = 0, eCRACK_RIGHT, eCRACK_UP, eCRACK_DOWN, eCRACK_LEFTUP, eCRACK_LEFTDOWN, eCRACK_RIGHTUP, eCRACK_RIGHTDOWN, eCRACK_MAX, }; unsigned int mIndexCount8x8; LPDIRECT3DINDEXBUFFER9 mIndexBuffer8x8; /// 4x4 LOD-1 unsigned int mIndexCount4x4; LPDIRECT3DINDEXBUFFER9 mIndexBuffer4x4; unsigned int mCrackIndexCount4x4[eCRACK_MAX]; LPDIRECT3DINDEXBUFFER9 mCrackIndexBuffer4x4[eCRACK_MAX]; /// 2x2 LOD-2 unsigned int mIndexCount2x2; LPDIRECT3DINDEXBUFFER9 mIndexBuffer2x2; unsigned int mCrackIndexCount2x2[eCRACK_MAX]; LPDIRECT3DINDEXBUFFER9 mCrackIndexBuffer2x2[eCRACK_MAX]; #ifdef MAP_EDITOR /// ºä ¸ðµå eTerrainViewMode mViewMode; /// º¯°æ ¿©ºÎ bool mModified; #endif }; inline bool cTerrain::IsInited() const { return mInited; } inline void cTerrain::SetLodEnabled( bool enabled ) { mLodEnabled = enabled; } inline NiAmbientLight* cTerrain::GetAmbientLight() const { return mAmbientLight; } inline cTerrainTexture* cTerrain::GetTexture( int i ) { if( i < 0 || i >= TERRAIN_TEXTURE_COUNT ) { assert( 0 && "index out of range" ); return 0; } else return mTextures[i]; } inline cTerrainBuffer* cTerrain::GetBuffer( unsigned int xi, unsigned int yi ) { return &(mBuffer[yi / TERRAIN_BUFF_CELL_COUNT][xi / TERRAIN_BUFF_CELL_COUNT]); } inline float cTerrain::GetHeightFast( unsigned int xi, unsigned int yi ) const { return mHeights[yi * mLineCount + xi]; } inline const NiPoint3& cTerrain::GetNormalFast( unsigned int xi, unsigned int yi ) const { return mNormals[yi * mLineCount + xi]; } inline void cTerrain::SetColor( unsigned int xi, unsigned int yi, const NiColor& color ) { mColors[yi * mLineCount + xi] = color; } inline const NiColor& cTerrain::GetColorFast( unsigned int xi, unsigned int yi ) const { return mColors[yi * mLineCount + xi]; } inline void cTerrain::SetAlpha( unsigned int xi, unsigned int yi, const NiPoint3& alpha ) { mAlphas[yi * mLineCount + xi] = alpha; } inline const NiPoint3& cTerrain::GetAlphaFast( unsigned int xi, unsigned int yi ) const { return mAlphas[yi * mLineCount + xi]; } inline const NiPoint3& cTerrain::GetPaintAlphaFast( unsigned int xi, unsigned int yi ) const { return mPaintAlphas[yi * mLineCount + xi]; } inline void cTerrain::SetPaintAlpha( unsigned int xi, unsigned int yi, const NiPoint3& alpha ) { mPaintAlphas[yi * mLineCount + xi] = alpha; } inline const float* cTerrain::GetHeights() const { return mHeights; } inline unsigned int cTerrain::GetCellCount() const { return mCellCount; } inline float cTerrain::GetMetersPerVertex() const { return mMetersPerVertex; } inline unsigned int cTerrain::GetUnitsPerMeter() const { return mUnitsPerMeter; } inline float cTerrain::GetUnitsPerVertex() const { return mUnitsPerVertex; } inline float cTerrain::GetUnitsPerLeafNode() const { return mUnitsPerLeafNode; } inline tArray& cTerrain::GetLeafNodeArray() { return mNodeArray; } inline unsigned int cTerrain::GetNumVisibleNodes() const { return mVisibleArray.GetSize(); } inline NiFogProperty* cTerrain::GetFogProperty() const { return mFogProp; } #ifdef MAP_EDITOR inline bool cTerrain::IsModified() const { return mModified; } #endif inline cTerrain* cTerrain::GetSingleton() { return mSingleton; } #define TERRAIN cTerrain::GetSingleton()