genesis-3d_engine/Engine/addons/terrainsystem/TerrainDataSource.h

608 lines
23 KiB
C
Raw Normal View History

/****************************************************************************
Copyright (c) 2011-2013,WebJet Business Division,CYOU
http://www.genesis-3d.com.cn
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#ifndef __TerrainDataSource_H__
#define __TerrainDataSource_H__
#include "core/refcounted.h"
#include "util/fixedarray2d.h"
#include "util/array.h"
#include "util/mipmaparray.h"
#include "math/color.h"
#include "resource/resourcemanager.h"
#include "resource/resourceserver.h"
namespace Resources
{
class TextureResInfo;
}
namespace Terrain
{
typedef Util::FixedArray2D<uint16> LocalYArray;
typedef Util::FixedArray2D<float> WorldYArray;
typedef Util::FixedArray2D<float> NormalizeLocalYArray;
typedef Util::FixedArray2D<uchar> HoleDataArray;
//------------------------------------------------------------------------------
//heightMap type
//------------------------------------------------------------------------------
#define SectorSize 17
#define UnitsInSector 16
#define InverseUnitsInSector 0.0625
#define UnitToSector 4
#define MaxHeightmapSize 2049
#define MaxLocalY 32766
//
enum HoleType
{
eNotHole = 0, // no hole
ePartHole = 1, // a part of grid is hole
eWholeHole =2 // complete hole
};
struct SSectorData
{
SSectorData()
{
mMinLocalY = 0;
mMaxLocalY = 0;
mGeoError = 0.0f;
mHoleType = eNotHole;
}
int mMinLocalY;
int mMaxLocalY;
float mGeoError; // geometry error
HoleType mHoleType;
};
struct DataSourceMapSetting
{
uint16 controlmapSize;
uint16 colormapSize;
uint16 basemapSize;
};
typedef Util::MipmapArray<SSectorData> SectorDataArray;
struct LayermapInfo
{
GPtr<Resources::TextureResInfo> resourceInfo;
Math::float2 layermapTileSize;
Math::float2 layermapOffset;
Resources::ResourceId materialName;
LayermapInfo()
:layermapTileSize(15.0f, 15.0f)
,layermapOffset(0.0f,0.0f)
{
}
};
typedef Util::Array<LayermapInfo> Layermaps;
typedef Util::Array< GPtr<Resources::TextureResInfo> > Controlmaps;
enum DataType
{
COLORF,
COLOR32
};
class TerrainDataSource : public Core::RefCounted
{
__DeclareClass(TerrainDataSource);
public:
TerrainDataSource();
virtual ~TerrainDataSource();
void SetDataSourceSetting(const DataSourceMapSetting& setting);
const DataSourceMapSetting& GetDataSourceSetting() const;
//------------------------------------------------------------------------------
//heightMap methods
//------------------------------------------------------------------------------
int GetHeightMapSize() const;
/// note ratio.y is maxWorldY / MaxLocalY
void SetTerrainRatio(const Math::float3& ratio);
const Math::float3 GetTerrainRatio() const;
int GetLevelCount() const;
int GetXUnitCount(int level) const;
int GetZUnitCount(int level) const;
float GetGeometryError (int xSector, int zSector, int level) const;
void SetWorldYByUnit(int xUnit,int zUnit,float y,int level = 0);
float GetWorldYByUnit(int xUnit,int zUnit,int level = 0) const;
void SetWorldYArrayByUnit(int xUnit,int zUnit,int xSize,int zSize, WorldYArray& yArray, int level = 0);
void GetWorldYArrayByUnit(int xUnit,int zUnit,int xSize,int zSize, WorldYArray& yArray, int level = 0) const;
void SetLocalYByUnit(int xUnit,int zUnit,uint16 y, int level = 0);
uint16 GetLocalYByUnit(int xUnit,int zUnit,int level = 0) const;
void SetNormalizeLocalYByUnit(int xUnit, int zUnit, float y, int level = 0);
float GetNormalizeLocalYByUnit(int xUnit, int zUnit, int level = 0) const;
void SetLocalYArrayByUnit(int xUnit,int zUnit,int xSize,int zSize, LocalYArray& yArray, int level = 0);
void GetLocalYArrayByUnit(int xUnit,int zUnit,int xSize,int zSize, LocalYArray& yArray, int level = 0) const;
void SetNormalizeLocalYArrayByUnit(int xUnit, int zUnit, int xSize, int zSize, const NormalizeLocalYArray& heights, int level = 0 );
void GetNormalizeLocalYArrayByUnit(int xUnit, int zUnit, int xSize, int zSize, NormalizeLocalYArray& heights, int level = 0) const;
// Get Interpolation worldY by xUnit,zUnit,and fX that is offset in the x direction
// and fZ that is offset in the z direction
float GetWorldYByUnit(int xUnit, int zUnit, float fX, float fZ, int level = 0) const;
IndexT GetSectorIndex(int xSector,int zSector,int level = 0) const;
void GetSectorLocalData(int xSector, int zSector, LocalYArray& aArray,int level = 0) const;
void GetSectorWorldData(int xSector, int zSector, WorldYArray& aArray,int level = 0) const;
Math::bbox GetSectorWorldBBox(int xSector,int zSector,int level = 0) const;
Math::bbox GetSectorLocalBBox(int xSector,int zSector,int level = 0) const;
/// [terrain:to be continue]
void CopySectorDatatFrom(const GPtr<TerrainDataSource>& obj);
void CalculateSectorInfoDataByUnit(int xUnit, int zUnit, int xSize, int zSize);
///LOD
void ResetSectorInfo(int xUnit, int zUnit, int xSize, int zSize);
Math::float3 CalculateWorldNormalByUnit(int xUnit, int zUnit, int level) const;
bool BuildHeightmpData(int heightmapSize, LocalYArray& yArray);
bool ResetHeightmpData(int heightmapSize, bool isUsePreData = false);
//------------------------------------------------------------------------------
//hole methods
//------------------------------------------------------------------------------
void SetHoleDataByUnit(int xUnit,int zUnit,uchar val);
uchar GetHoleDataByUnit(int xUnit,int zUnit) const;
HoleType GetSectorHoleType(int xSector, int zSector, int level) const;
HoleType CalculateMaxDetailedSectorHoleType(int xSector, int zSector) const;
uint CalcualteMipGridHoleCount(int xUnit, int zUnit, int mipLevel) const;
//------------------------------------------------------------------------------
//LayerMap methods
//------------------------------------------------------------------------------
void SetLayermaps(const Layermaps & layermaps);
const Layermaps& GetLayermpas() const;
void AddLayermap(int layerIndex, LayermapInfo layermapInfo);
void DelLayermap(int layerIndex);
void SetLayermap(int layerIndex, LayermapInfo layermapInfo);
LayermapInfo GetLayermap(int layerIndex);
int GetLayerMapCount() const;
//------------------------------------------------------------------------------
//ControlMap methods
// Set/Get Control/Color/Base MapData methods should use template function! /// [terrain:to be continue]
//------------------------------------------------------------------------------
bool IsValidControlMap() const;
bool CreateControlMap(const Resources::ResourceId& resID);
GPtr<Resources::TextureResInfo>& GetControlMap(const int idx);
void AddControlMap(GPtr<Resources::TextureResInfo>& texInfo);
void DelControlMap(const int idx);
int GetControlMapSize() const;
void GetControlMapData(Math::Color32* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
void GetControlMapData(Math::ColorF* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
void SetControlMapData(Math::Color32* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
void SetControlMapData(Math::ColorF* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
void RefreshControlMap(const int index,int texNumBeforeDel);
//------------------------------------------------------------------------------
//ColorMap methods
//------------------------------------------------------------------------------
bool IsValidColormap() const;
bool CreateColorMap(const Resources::ResourceId& resID);
void SetColorMap(GPtr<Resources::TextureResInfo>& texInfo);
void GetColorMapData(Math::Color32* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
void GetColorMapData(Math::ColorF* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
void SetColorMapData(Math::Color32* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
void SetColorMapData(Math::ColorF* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
//------------------------------------------------------------------------------
//BaseMap methods
//------------------------------------------------------------------------------
bool IsValidBasemap() const;
bool CreateBaseMap(const Resources::ResourceId& resID);
void SetBaseMap(GPtr<Resources::TextureResInfo>& texInfo);
void GetBaseMapData(Math::Color32* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
void GetBaseMapData(Math::ColorF* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
void SetBaseMapData(Math::Color32* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
void SetBaseMapData(Math::ColorF* buffer,const int xStart = 0,const int yStart = 0,const int width = -1,const int height = -1);
//void RefreshBasemap(const int xStart = 0,const int yStart = 0, const int width = -1, const int height = -1 );
void RefreshBasemap(float xStart = 0.0f, float yStart = 0.0f, float relativeWidth = 1.0f, float relativeHeight = 1.0f);
//------------------------------------------------------------------------------
//other unclassify methods
//------------------------------------------------------------------------------
void SaveAllMaps();
void SaveControlMap();
void SaveColorMap();
void SaveBaseMap();
protected:
void _GetBlendWeights(int xStart, int yStart, int width, int height, float* buffer);
bool GetImagesData(GPtr<Resources::TextureResInfo> & texResInfo, int xStart, int yStart, int width, int height, void* buffer, DataType datatype);
bool SetImagesData(GPtr<Resources::TextureResInfo> & texResInfo, int xStart, int yStart, int width, int height, void* buffer, DataType datatype);
void _saveImage(GPtr<Resources::TextureResInfo> & texResInfo);
void CalculateASectorGeoErrorDataBySector(int xSector, int zSector, int level);
void CalculateASectorMinMaxLocalYDataBySector(int xSector, int zSector, int level, int& maxLocalY,int& minLocalY );
void CalculateASectorMinMaxYDataBySector(int xSector, int zSector);
private:
static void _UpdateTextureFunction(RenderBase::Texture::MapInfo& texMap,int width,int height, int depth, RenderBase::PixelFormat::Code format, int mipLevel, void* tag);
private:
DataSourceMapSetting mapSetting;
LocalYArray mLocalYArray;
HoleDataArray mHoleDataArray; // we can't use std::bitset,because holedata' size will changing wtih height map size
SectorDataArray mSectorData;
float mYRatio;
Math::float2 mXZRatio;
Math::float3 mWorldSize;
int mHeightmapSize;
Layermaps mLayermaps;
Controlmaps mControlmaps;
GPtr<Resources::TextureResInfo> mBaseMap;
GPtr<Resources::TextureResInfo> mColorMap;
};
//==============================================================================================================
inline void TerrainDataSource::SetDataSourceSetting(const DataSourceMapSetting& setting)
{
mapSetting = setting;
}
inline const DataSourceMapSetting& TerrainDataSource::GetDataSourceSetting() const
{
return mapSetting;
}
inline int TerrainDataSource::GetHeightMapSize() const
{
return mHeightmapSize;
}
inline void TerrainDataSource::SetTerrainRatio(const Math::float3& ratio)
{
mXZRatio.x() = ratio.x();
mYRatio = ratio.y();
mXZRatio.y() = ratio.z();
}
inline const Math::float3 TerrainDataSource::GetTerrainRatio() const
{
return Math::float3(mXZRatio.x(),mYRatio,mXZRatio.y());
}
inline int TerrainDataSource::GetLevelCount() const
{
return mSectorData.GetMipCount();
}
inline int TerrainDataSource::GetXUnitCount(int level) const
{
n_assert( level < mSectorData.GetMipCount() );
return (mSectorData.RowSize(level) << UnitToSector) + 1;
}
inline int TerrainDataSource::GetZUnitCount(int level) const
{
n_assert( level < mSectorData.GetMipCount() );
return (mSectorData.ColSize(level) << UnitToSector) + 1;
}
inline float TerrainDataSource::GetGeometryError (int xSector, int zSector, int level) const
{
n_assert( level < mSectorData.GetMipCount() );
n_assert( xSector >= 0 && xSector < mSectorData.RowSize( level ) );
n_assert( zSector >= 0 && zSector < mSectorData.ColSize( level ) );
return mSectorData.At( xSector, zSector, level ).mGeoError;
}
inline void TerrainDataSource::SetLayermaps(const Layermaps & layermaps)
{
mLayermaps = layermaps;
}
inline const Layermaps& TerrainDataSource::GetLayermpas() const
{
return mLayermaps;
}
inline int TerrainDataSource::GetLayerMapCount() const
{
return mLayermaps.Size();
}
inline void TerrainDataSource::SetWorldYByUnit(int xUnit, int zUnit, float y, int level)
{
n_assert( level >= 0 && level < mSectorData.GetMipCount() );
n_assert( xUnit >= 0 && xUnit <= (mSectorData.RowSize(level) << UnitToSector) );
n_assert( zUnit >= 0 && zUnit <= (mSectorData.ColSize(level) << UnitToSector) );
uint16 localY = (uint16)(y / mYRatio);
mLocalYArray.At(xUnit << level, zUnit << level) = localY;
}
inline float TerrainDataSource::GetWorldYByUnit(int xUnit, int zUnit, int level) const
{
n_assert( level >= 0 && level < mSectorData.GetMipCount() );
n_assert( xUnit >= 0 && xUnit <= (mSectorData.RowSize(level) << UnitToSector) );
n_assert( zUnit >= 0 && zUnit <= (mSectorData.ColSize(level) << UnitToSector) );
float worldY = mLocalYArray.At(xUnit << level, zUnit << level) * mYRatio;
return worldY;
}
inline void TerrainDataSource::SetLocalYByUnit(int xUnit,int zUnit,uint16 y, int level)
{
n_assert( level >= 0 && level < mSectorData.GetMipCount() );
n_assert( xUnit >= 0 && xUnit <= (mSectorData.RowSize(level) << UnitToSector) );
n_assert( zUnit >= 0 && zUnit <= (mSectorData.ColSize(level) << UnitToSector) );
mLocalYArray.At(xUnit << level, zUnit << level) = y;
}
inline uint16 TerrainDataSource::GetLocalYByUnit(int xUnit,int zUnit,int level) const
{
n_assert( level >= 0 && level < mSectorData.GetMipCount() );
n_assert( xUnit >= 0 && xUnit <= (mSectorData.RowSize(level) << UnitToSector) );
n_assert( zUnit >= 0 && zUnit <= (mSectorData.ColSize(level) << UnitToSector) );
return mLocalYArray.At(xUnit << level, zUnit << level);
}
inline void TerrainDataSource::SetNormalizeLocalYByUnit(int xUnit, int zUnit, float y, int level)
{
n_assert( level >= 0 && level < mSectorData.GetMipCount() );
n_assert( xUnit >= 0 && xUnit <= (mSectorData.RowSize(level) << UnitToSector) );
n_assert( zUnit >= 0 && zUnit <= (mSectorData.ColSize(level) << UnitToSector) );
int localY = (int)(y * MaxLocalY + 0.5f);
mLocalYArray.At(xUnit << level, zUnit << level) = Math::n_clamp(localY, 0, MaxLocalY);
}
inline float TerrainDataSource::GetNormalizeLocalYByUnit(int xUnit, int zUnit, int level) const
{
n_assert( level >= 0 && level < mSectorData.GetMipCount() );
n_assert( xUnit >= 0 && xUnit <= (mSectorData.RowSize(level) << UnitToSector) );
n_assert( zUnit >= 0 && zUnit <= (mSectorData.ColSize(level) << UnitToSector) );
uint16 localY = mLocalYArray.At(xUnit << level, zUnit << level);
return localY * 1.0f / MaxLocalY;
}
inline float TerrainDataSource::GetWorldYByUnit(int xUnit, int zUnit, float fX, float fZ, int level) const
{
n_assert( level >= 0 && level < mSectorData.GetMipCount() );
n_assert( xUnit >= 0 && xUnit <= (mSectorData.RowSize( level ) << UnitToSector) );
n_assert( zUnit >= 0 && zUnit <= (mSectorData.ColSize( level ) << UnitToSector) );
n_assert( fX >= 0 && fX <= 1);
n_assert( fZ >= 0 && fZ <= 1);
float fLocalY = GetLocalYByUnit(xUnit, zUnit, level) * (1.f - fX) * (1 - fZ)
+ GetLocalYByUnit(xUnit + 1, zUnit, level) * fX * (1.f - fZ)
+ GetLocalYByUnit(xUnit, zUnit + 1, level) * (1.f - fX) * fZ
+ GetLocalYByUnit(xUnit + 1, zUnit + 1, level) * fX * fZ;
return fLocalY * mYRatio;
}
inline IndexT TerrainDataSource::GetSectorIndex(int xSector,int zSector,int level) const
{
return mSectorData.Index(xSector, zSector, level);
}
inline void TerrainDataSource::CalculateASectorMinMaxYDataBySector(int xSector, int zSector)
{
int startXUnit = xSector << UnitToSector;
int startZUnit = zSector << UnitToSector;
int endXUnit = startXUnit + SectorSize;
int endZUnit = startZUnit + SectorSize;
int minLocalY = MaxLocalY;
int maxLocalY = -MaxLocalY;
for (int x = startXUnit; x < endXUnit; x++)
{
for (int z = startZUnit; z < endZUnit; z++)
{
int localY = GetLocalYByUnit(x, z, 0);
minLocalY = localY < minLocalY ? localY : minLocalY;
maxLocalY = localY > maxLocalY ? localY : maxLocalY;
}
}
mSectorData.At(xSector, zSector, 0).mMinLocalY = minLocalY;
mSectorData.At(xSector, zSector, 0).mMaxLocalY = maxLocalY;
}
inline void TerrainDataSource::CalculateASectorGeoErrorDataBySector(int xSector, int zSector, int level)
{
if (level == 0)
{
mSectorData.At(xSector, zSector, level).mGeoError = 0.0f;
return;
}
int startXUnit = xSector << ( UnitToSector + level );
int startZUnit = zSector << ( UnitToSector + level );
int endXUnit = startXUnit + ( UnitsInSector << level ) + 1;
int endZUnit = startZUnit + ( UnitsInSector << level ) + 1;
float inverseLodSize = 1.0f / (1 << level);
float geoError = 0.0f;
// first xUnit and last xUnit when geoError is 0.f
// first zUnit and last zUnit when geoError is 0.f
startXUnit++;
startZUnit++;
endXUnit--;
endZUnit--;
for (int x = startXUnit; x < endXUnit; x++)
{
for (int z = startZUnit; z < endZUnit; z++)
{
float trueWorldY = GetWorldYByUnit(x, z, 0);
int xUnit = x >> level;
int zUnit = z >> level;
float fx = (x - (xUnit << level) ) * inverseLodSize;
float fz = (z - (zUnit << level) ) * inverseLodSize;
float interpolatedWorldY = GetWorldYByUnit(xUnit, zUnit, fx, fz, level);
float deltaY = Math::n_abs(interpolatedWorldY - trueWorldY);
geoError = deltaY > geoError ? deltaY : geoError;
}
}
mSectorData.At(xSector, zSector, level).mGeoError = geoError;
}
inline void TerrainDataSource::CalculateASectorMinMaxLocalYDataBySector(int xSector, int zSector, int level, int& maxLocalY,int& minLocalY )
{
SSectorData & sectorData1 = mSectorData.At( xSector << 1, zSector << 1, level - 1);
SSectorData & sectorData2 = mSectorData.At( (xSector << 1) + 1, zSector << 1, level - 1);
SSectorData & sectorData3 = mSectorData.At( (xSector << 1), (zSector << 1) + 1, level - 1);
SSectorData & sectorData4 = mSectorData.At( (xSector << 1) + 1, (zSector << 1) + 1, level - 1);
minLocalY = sectorData1.mMinLocalY < minLocalY ? sectorData1.mMinLocalY : minLocalY;
minLocalY = sectorData2.mMinLocalY < minLocalY ? sectorData2.mMinLocalY : minLocalY;
minLocalY = sectorData3.mMinLocalY < minLocalY ? sectorData3.mMinLocalY : minLocalY;
minLocalY = sectorData4.mMinLocalY < minLocalY ? sectorData4.mMinLocalY : minLocalY;
maxLocalY = sectorData1.mMaxLocalY > maxLocalY ? sectorData1.mMaxLocalY : maxLocalY;
maxLocalY = sectorData2.mMaxLocalY > maxLocalY ? sectorData2.mMaxLocalY : maxLocalY;
maxLocalY = sectorData3.mMaxLocalY > maxLocalY ? sectorData3.mMaxLocalY : maxLocalY;
maxLocalY = sectorData4.mMaxLocalY > maxLocalY ? sectorData4.mMaxLocalY : maxLocalY;
}
inline bool TerrainDataSource::IsValidControlMap() const
{
return mControlmaps.Size() > 0;
}
inline GPtr<Resources::TextureResInfo>& TerrainDataSource::GetControlMap(const int idx)
{
n_assert( idx >= 0 && idx < mControlmaps.Size() );
return mControlmaps[idx];
}
inline void TerrainDataSource::DelControlMap(const int idx)
{
n_assert( idx >= 0 && idx < mControlmaps.Size() );
mControlmaps.EraseIndex(idx);
}
inline int TerrainDataSource::GetControlMapSize() const
{
return mControlmaps.Size();
}
inline void TerrainDataSource::AddControlMap(GPtr<Resources::TextureResInfo>& texInfo)
{
mControlmaps.Append( texInfo );
}
inline uchar TerrainDataSource::GetHoleDataByUnit(int xUnit,int zUnit) const
{
n_assert( xUnit >= 0 && xUnit <= (mSectorData.RowSize(0) << UnitToSector) );
n_assert( zUnit >= 0 && zUnit <= (mSectorData.ColSize(0) << UnitToSector) );
return mHoleDataArray.At(xUnit, zUnit);
}
inline HoleType TerrainDataSource::GetSectorHoleType(int xSector, int zSector, int level) const
{
n_assert( level < mSectorData.GetMipCount() );
n_assert( xSector >= 0 && xSector < mSectorData.RowSize( level ) );
n_assert( zSector >= 0 && zSector < mSectorData.ColSize( level ) );
return mSectorData.At( xSector, zSector, level ).mHoleType;
}
inline HoleType TerrainDataSource::CalculateMaxDetailedSectorHoleType(int xSector, int zSector) const
{
int startXUnit = xSector << UnitToSector;
int startZUnit = zSector << UnitToSector;
int endXUnit = startXUnit + UnitsInSector;
int endZUnit = startZUnit + UnitsInSector;
int total(0);
for (int x = startXUnit; x < endXUnit; x++)
{
for (int z = startZUnit; z < endZUnit; z++)
{
if ( mHoleDataArray.At(x,z) == 1 )
{
total++;
}
}
}
HoleType hole(eNotHole);
if ( total == 0 )
{
hole = eNotHole;
}
else if ( total < UnitsInSector* UnitsInSector)
{
hole = ePartHole;
}
else
{
hole = eWholeHole;
}
return hole;
}
inline uint TerrainDataSource::CalcualteMipGridHoleCount(int xUnit, int zUnit, int mipLevel) const
{
if ( mipLevel == 0 )
{
return mHoleDataArray.At(xUnit,zUnit)==1? 1: 0;
}
else
{
int startXUnit = xUnit << mipLevel;
int startZUnit = zUnit << mipLevel;
int endXUnit = startXUnit + (1<<mipLevel);
int endZUnit = startZUnit + (1<<mipLevel);
int total(0);
for (int x = startXUnit; x < endXUnit; x++)
{
for (int z = startZUnit; z < endZUnit; z++)
{
if ( mHoleDataArray.At(x,z) == 1 )
{
total++;
}
}
}
return total;
}
}
}
#endif // __TerrainDataSource_H__