Пример #1
0
void TerrainLattice::CalcGeoMipmapLod(float x,float y)
{
	Terrain* pTerrain = m_pCachedTerrains[m_CurrentTerrainIndex[0]].pTerrain;
	int blockCountX = (pTerrain->GetWidthVertices()-1) / pTerrain->GetMaximumVisibleBlockSize();

	float blockSize = m_TerrainWidth/blockCountX;
	int terrainCountX = (int)x / (int)m_TerrainWidth;
	int terrainCountY = (int)y / (int)m_TerrainHeight;
	x = x - terrainCountX * (int)m_TerrainWidth;
	y = y - terrainCountY * (int)m_TerrainHeight;

	int centerChunkIdxX = (int)(x / blockSize) + blockCountX;
	int centerChunkIdxY = (int)(y / blockSize) + blockCountX;

	int lodBounds[8];
	int halfWidth = m_Level0ChunkCount / 2;
	lodBounds[0] = centerChunkIdxX - halfWidth;
	lodBounds[1] = centerChunkIdxX + halfWidth;
	lodBounds[2] = centerChunkIdxY - halfWidth;
	lodBounds[3] = centerChunkIdxY + halfWidth;
	halfWidth = m_Level1ChunkCount / 2;
	lodBounds[4] = lodBounds[0] - halfWidth;
	lodBounds[5] = lodBounds[1] +	halfWidth;
	lodBounds[6] = lodBounds[2] -	halfWidth;
	lodBounds[7] = lodBounds[3] + halfWidth;

	const int leftFlag = 0x01;
	const int rightFlag = 0x02;
	const int topFlag = 0x04;
	const int bottomFlag = 0x08;

	//calc lod for each block in each terrain
	for (int dir = 0; dir < 9 ; dir++)
	{
		TerrainTileCacheMap_type::iterator iter = m_pCachedTerrains.find(m_CurrentTerrainIndex[dir]);
		if(iter != m_pCachedTerrains.end())
		{
			int startBlockIdxX = 0;
			int startBlockIdxY = 0;
			Terrain* pTerrain = (*iter).second.pTerrain;

			if(dir == DIR_CENTER)
			{
				startBlockIdxX = blockCountX;
				startBlockIdxY = blockCountX;
			}
			else if(dir == DIR_NORTH)
			{
				startBlockIdxX = blockCountX;
				startBlockIdxY = blockCountX * 2;
			}
			else if(dir == DIR_NORTHEAST)
			{
				startBlockIdxX = blockCountX * 2;
				startBlockIdxY = blockCountX * 2;
			}
			else if(dir == DIR_EAST)
			{
				startBlockIdxX = blockCountX * 2;
				startBlockIdxY = blockCountX;
			}
			else if(dir == DIR_SOUTHEAST)
			{
				startBlockIdxX = blockCountX * 2;
				startBlockIdxY = 0;
			}
			else if(dir == DIR_SOUTH)
			{
				startBlockIdxX = blockCountX;
				startBlockIdxY = 0;
			}
			else if(dir == DIR_SOUTHWEST)
			{
				startBlockIdxX = 0;
				startBlockIdxY = 0;
			}
			else if(dir == DIR_WEST)
			{
				startBlockIdxX = 0;
				startBlockIdxY = blockCountX;
			}
			else if(dir == DIR_NORTHWEST)
			{
				startBlockIdxX = 0;
				startBlockIdxY = blockCountX * 2;
			}

			for(int i=0;i<blockCountX;i++)
			{
				for(int j=0;j<blockCountX;j++)
				{
					int blockX = startBlockIdxX + j;
					int blockY = startBlockIdxY + i;

					int level = CalcBlockLod(lodBounds,blockX,blockY,3);
					int blockType = 0;

					int leftBlock = CalcBlockLod(lodBounds,blockX-1,blockY,3);
					if(leftBlock > level)
						blockType |= leftFlag;

					int rightBlock = CalcBlockLod(lodBounds,blockX+1,blockY,3);
					if(rightBlock > level)
						blockType |= rightFlag;

					int topBlock = CalcBlockLod(lodBounds,blockX,blockY-1,3);
					if(topBlock > level)
						blockType |= topFlag;

					int bottomBlock = CalcBlockLod(lodBounds,blockX,blockY+1,3);
					if(bottomBlock > level)
						blockType |= bottomFlag;

					GeoMipmapChunkType chunkType;
					switch (blockType)
					{
					case leftFlag|rightFlag|topFlag|bottomFlag:
						chunkType = gmc_surrounded;
						break;
					case topFlag | leftFlag:
						chunkType = gmc_topLeft;
						break;
					case leftFlag:
						chunkType = gmc_left;
						break;
					case bottomFlag | leftFlag:
						chunkType = gmc_bottomLeft;
						break;
					case bottomFlag:
						chunkType = gmc_bottom;
						break;
					case bottomFlag | rightFlag:
						chunkType = gmc_bottomRight;
						break;
					case rightFlag:
						chunkType = gmc_right;
						break;
					case topFlag | rightFlag:
						chunkType = gmc_topRight;
						break;
					case topFlag:
						chunkType = gmc_top;
						break;
					default:
						chunkType = gmc_normal;
						break;
					}					
					pTerrain->SetBlockLod(i,j,level,chunkType);									
				}
			}
		}
	}
}