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); } } } } }