GLvoid CBlock::init() { // 1. setup visible surfaces if (isLow()) { visible[BFS_TOP] = false; visible[BFS_WATER_LAVA] = isWater() || isLava(); visible[BFS_BOTTOM] = !visible[BFS_WATER_LAVA]; visible[BFS_CEILING] = true; } else { visible[BFS_TOP] = true; visible[BFS_BOTTOM] = false; visible[BFS_WATER_LAVA] = false; visible[BFS_CEILING] = false; } //visible[BFS_TOP] = false; // uncomment to see the optimization vector2i tests[4] = { vector2i(0,1), // BFS_FRONT vector2i(0,-1), // BFS_BACK vector2i(-1,0), // BFS_LEFT vector2i(1,0), // BFS_RIGHT }; CBlock *testBlock = NULL; for (GLint i=BFS_FRONT; i<=BFS_RIGHT; i++) { testBlock = CV_GAME_MANAGER->getLevelManager()->getBlock(logicalPosition+tests[i]); visible[i] = isLow()?false:(testBlock && testBlock->isLow() || !testBlock); if (water || lava) { // since water and lava are submerged by 1 level we nned to handle them differently visible[i] = testBlock && (!testBlock->low || testBlock->type==CV_BLOCK_TYPE_CLAIMED_LAND_ID || testBlock->type==CV_BLOCK_TYPE_UNCLAIMED_LAND_ID); } } // tmp /*for (GLint v=BFS_FRONT+1; v<=BFS_WATER_LAVA; v++) { //if (v!=BFS_BOTTOM) { visible[v]=false; } }*/ /* For every block change you must call: - block init - calc block height if needed - finalize */ }
bool CBlock::isBuildable(GLint playerID) { if (isWater() || isLava()) { return true; } return (type == CV_BLOCK_TYPE_CLAIMED_LAND_ID && playerID == owner && !isSellable(playerID)); }
void CPlanetTextureGenerator::genThreadWorker(const CHeightMap* heightMap, unsigned char* pixels, const unsigned int textureWidth, int part) { const unsigned int width = heightMap->getWidth(); const unsigned int bpp = 4; glm::fvec3 currColor; unsigned int startX = 0; unsigned int stopX = width / 2; unsigned int startY = 0; unsigned int stopY = width / 2; if (part == 2) { startX = width / 2; stopX = width; startY = 0 ; stopY = width / 2; } if (part == 3) { startX = 0; stopX = width / 2; startY = width / 2; stopY = width; } if (part == 4) { startX = width / 2; stopX = width; startY = width / 2; stopY = width; } unsigned int y; unsigned int x; for ( y = startY; y < stopY; y++) { for ( x = startX; x < stopX; x++) { currColor = getTerrainColor(x, y, heightMap); pixels[(y*textureWidth + x)*bpp + 0] = (int)(currColor.r * 255); pixels[(y*textureWidth + x)*bpp + 1] = (int)(currColor.g * 255); pixels[(y*textureWidth + x)*bpp + 2] = (int)(currColor.b * 255); pixels[(y*textureWidth + x)*bpp + 3] = 255; if (isWater(x, y, heightMap) && hasLiquidTexture) { unsigned int pos = (y * textureWidth + width + x) * bpp; if (hasCloudTexture) pos = (y * textureWidth + width * 2 + x) * bpp; pixels[pos + 0] = 255; pixels[pos + 3] = 255; } } } CLog::getInstance()->addInfo("genThread stoped " + std::to_string(x) + " " + std::to_string(y)); }
int TerrainTile::encode() const { int res = 0; if (isTree()) { res += 0x1; res += 0x10; } if (isRock()) { res += 0x2; } if (isWater()) { res += 0x4; } if (isBuilding()) { res += 0x8; } if (isRoad()) { res += 0x40; } return res; }
Uint16 Level::findWaterType() const { for (Int32 y = 0; y < getHeight(); y++) { for (Int32 x = 0; x < getWidth(); x++) { if (isWater(x, y)) { return getBlock(x, y); } } } Uint16 waterBlocks[] = { 4, 16, 33 }; return waterBlocks[rand() % 3]; }
// TAC - AI Explore from Ship endless loop fix - koma13 - START bool CvArea::isEuropePlayer() const { if (isWater()) { return false; } for (int iI = 0; iI < MAX_PLAYERS; iI++) { CvPlayerAI& kLoopPlayer = GET_PLAYER((PlayerTypes)iI); if (kLoopPlayer.isAlive() && !kLoopPlayer.isNative()) { if (this->getCitiesPerPlayer((PlayerTypes)iI) > 0) { return true; } } } return false; }
Water::Type Level::getWaterType(Int32 x, Int32 y) const { if (isWater(x, y)) { Uint16 block = getBlock(x, y); if (block == 4) { return Water::Type::Blue; } else if (block == 16) { return Water::Type::Red; } else if (block == 33) { return Water::Type::Green; } } return Water::Type::None; }
int CvArea::countCoastalLand() const { if (isWater()) { return 0; } int iCount = 0; for (int iI = 0; iI < GC.getMapINLINE().numPlotsINLINE(); iI++) { CvPlot* pLoopPlot = GC.getMapINLINE().plotByIndexINLINE(iI); if (pLoopPlot->getArea() == getID()) { if (pLoopPlot->isCoastalLand()) { iCount++; } } } return iCount; }
/** * Check what the videocard + drivers support and divide the loaded map into sectors that can be drawn. * It also determines the lightmap size. */ bool initTerrain(void) { int i, j, x, y, a, b, absX, absY; PIELIGHT colour[2][2], centerColour; int layer = 0; RenderVertex *geometry; RenderVertex *water; DecalVertex *decaldata; int geometrySize, geometryIndexSize; int waterSize, waterIndexSize; int textureSize, textureIndexSize; GLuint *geometryIndex; GLuint *waterIndex; GLuint *textureIndex; PIELIGHT *texture; int decalSize; int maxSectorSizeIndices, maxSectorSizeVertices; bool decreasedSize = false; // call VBO support hack before using it screen_EnableVBO(); // this information is useful to prevent crashes with buggy opengl implementations glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, &GLmaxElementsVertices); glGetIntegerv(GL_MAX_ELEMENTS_INDICES, &GLmaxElementsIndices); // testing for crappy cards debug(LOG_TERRAIN, "GL_MAX_ELEMENTS_VERTICES: %i", (int)GLmaxElementsVertices); debug(LOG_TERRAIN, "GL_MAX_ELEMENTS_INDICES: %i", (int)GLmaxElementsIndices); // now we know these values, determine the maximum sector size achievable maxSectorSizeVertices = iSqrt(GLmaxElementsVertices/2)-1; maxSectorSizeIndices = iSqrt(GLmaxElementsIndices/12); debug(LOG_TERRAIN, "preferred sector size: %i", sectorSize); debug(LOG_TERRAIN, "maximum sector size due to vertices: %i", maxSectorSizeVertices); debug(LOG_TERRAIN, "maximum sector size due to indices: %i", maxSectorSizeIndices); if (sectorSize > maxSectorSizeVertices) { sectorSize = maxSectorSizeVertices; decreasedSize = true; } if (sectorSize > maxSectorSizeIndices) { sectorSize = maxSectorSizeIndices; decreasedSize = true; } if (decreasedSize) { if (sectorSize < 1) { debug(LOG_WARNING, "GL_MAX_ELEMENTS_VERTICES: %i", (int)GLmaxElementsVertices); debug(LOG_WARNING, "GL_MAX_ELEMENTS_INDICES: %i", (int)GLmaxElementsIndices); debug(LOG_WARNING, "maximum sector size due to vertices: %i", maxSectorSizeVertices); debug(LOG_WARNING, "maximum sector size due to indices: %i", maxSectorSizeIndices); debug(LOG_ERROR, "Your graphics card and/or drivers do not seem to support glDrawRangeElements, needed for the terrain renderer."); debug(LOG_ERROR, "- Do other 3D games work?"); debug(LOG_ERROR, "- Did you install the latest drivers correctly?"); debug(LOG_ERROR, "- Do you have a 3D window manager (Aero/Compiz) running?"); return false; } debug(LOG_WARNING, "decreasing sector size to %i to fit graphics card constraints", sectorSize); } // +4 = +1 for iHypot rounding, +1 for sector size rounding, +2 for edge of visibility terrainDistance = iHypot(visibleTiles.x/2, visibleTiles.y/2)+4+sectorSize/2; debug(LOG_TERRAIN, "visible tiles x:%i y: %i", visibleTiles.x, visibleTiles.y); debug(LOG_TERRAIN, "terrain view distance: %i", terrainDistance); ///////////////////// // Create the sectors xSectors = (mapWidth +sectorSize-1)/sectorSize; ySectors = (mapHeight+sectorSize-1)/sectorSize; sectors = (Sector *)malloc(sizeof(Sector)*xSectors*ySectors); //////////////////// // fill the geometry part of the sectors geometry = (RenderVertex *)malloc(sizeof(RenderVertex)*xSectors*ySectors*(sectorSize+1)*(sectorSize+1)*2); geometryIndex = (GLuint *)malloc(sizeof(GLuint)*xSectors*ySectors*sectorSize*sectorSize*12); geometrySize = 0; geometryIndexSize = 0; water = (RenderVertex *)malloc(sizeof(RenderVertex)*xSectors*ySectors*(sectorSize+1)*(sectorSize+1)*2); waterIndex = (GLuint *)malloc(sizeof(GLuint)*xSectors*ySectors*sectorSize*sectorSize*12); waterSize = 0; waterIndexSize = 0; for (x = 0; x < xSectors; x++) { for (y = 0; y < ySectors; y++) { sectors[x*ySectors + y].dirty = false; sectors[x*ySectors + y].geometryOffset = geometrySize; sectors[x*ySectors + y].geometrySize = 0; sectors[x*ySectors + y].waterOffset = waterSize; sectors[x*ySectors + y].waterSize = 0; setSectorGeometry(x, y, geometry, water, &geometrySize, &waterSize); sectors[x*ySectors + y].geometrySize = geometrySize - sectors[x*ySectors + y].geometryOffset; sectors[x*ySectors + y].waterSize = waterSize - sectors[x*ySectors + y].waterOffset; // and do the index buffers sectors[x*ySectors + y].geometryIndexOffset = geometryIndexSize; sectors[x*ySectors + y].geometryIndexSize = 0; sectors[x*ySectors + y].waterIndexOffset = waterIndexSize; sectors[x*ySectors + y].waterIndexSize = 0; for (i = 0; i < sectorSize; i++) { for (j = 0; j < sectorSize; j++) { if (x*sectorSize+i >= mapWidth || y*sectorSize+j >= mapHeight) { continue; // off map, so skip } /* One tile is composed of 4 triangles, * we need _2_ vertices per tile (1) * e.g. center and bottom left * the other 3 vertices are from the adjacent tiles * on their top and right. * (1) The top row and right column of tiles need 4 vertices per tile * because they do not have adjacent tiles on their top and right, * that is why we add _1_ row and _1_ column to provide the geometry * for these tiles. * This is the source of the '*2' and '+1' in the index math below. */ #define q(i,j,center) ((x*ySectors+y)*(sectorSize+1)*(sectorSize+1)*2 + ((i)*(sectorSize+1)+(j))*2+(center)) // First triangle geometryIndex[geometryIndexSize+0] = q(i ,j ,1); // Center vertex geometryIndex[geometryIndexSize+1] = q(i ,j ,0); // Bottom left geometryIndex[geometryIndexSize+2] = q(i+1,j ,0); // Bottom right // Second triangle geometryIndex[geometryIndexSize+3] = q(i ,j ,1); // Center vertex geometryIndex[geometryIndexSize+4] = q(i ,j+1,0); // Top left geometryIndex[geometryIndexSize+5] = q(i ,j ,0); // Bottom left // Third triangle geometryIndex[geometryIndexSize+6] = q(i ,j ,1); // Center vertex geometryIndex[geometryIndexSize+7] = q(i+1,j+1,0); // Top right geometryIndex[geometryIndexSize+8] = q(i ,j+1,0); // Top left // Fourth triangle geometryIndex[geometryIndexSize+9] = q(i ,j ,1); // Center vertex geometryIndex[geometryIndexSize+10] = q(i+1,j ,0); // Bottom right geometryIndex[geometryIndexSize+11] = q(i+1,j+1,0); // Top right geometryIndexSize += 12; if (isWater(i+x*sectorSize,j+y*sectorSize)) { waterIndex[waterIndexSize+0] = q(i ,j ,1); waterIndex[waterIndexSize+1] = q(i ,j ,0); waterIndex[waterIndexSize+2] = q(i+1,j ,0); waterIndex[waterIndexSize+3] = q(i ,j ,1); waterIndex[waterIndexSize+4] = q(i ,j+1,0); waterIndex[waterIndexSize+5] = q(i ,j ,0); waterIndex[waterIndexSize+6] = q(i ,j ,1); waterIndex[waterIndexSize+7] = q(i+1,j+1,0); waterIndex[waterIndexSize+8] = q(i ,j+1,0); waterIndex[waterIndexSize+9] = q(i ,j ,1); waterIndex[waterIndexSize+10] = q(i+1,j ,0); waterIndex[waterIndexSize+11] = q(i+1,j+1,0); waterIndexSize += 12; } } } sectors[x*ySectors + y].geometryIndexSize = geometryIndexSize - sectors[x*ySectors + y].geometryIndexOffset; sectors[x*ySectors + y].waterIndexSize = waterIndexSize - sectors[x*ySectors + y].waterIndexOffset; } } glGenBuffers(1, &geometryVBO); glError(); glBindBuffer(GL_ARRAY_BUFFER, geometryVBO); glError(); glBufferData(GL_ARRAY_BUFFER, sizeof(RenderVertex)*geometrySize, geometry, GL_DYNAMIC_DRAW); glError(); free(geometry); glGenBuffers(1, &geometryIndexVBO); glError(); glBindBuffer(GL_ARRAY_BUFFER, geometryIndexVBO); glError(); glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint)*geometryIndexSize, geometryIndex, GL_STATIC_DRAW); glError(); free(geometryIndex); glGenBuffers(1, &waterVBO); glError(); glBindBuffer(GL_ARRAY_BUFFER, waterVBO); glError(); glBufferData(GL_ARRAY_BUFFER, sizeof(RenderVertex)*waterSize, water, GL_DYNAMIC_DRAW); glError(); free(water); glGenBuffers(1, &waterIndexVBO); glError(); glBindBuffer(GL_ARRAY_BUFFER, waterIndexVBO); glError(); glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint)*waterIndexSize, waterIndex, GL_STATIC_DRAW); glError(); free(waterIndex); glBindBuffer(GL_ARRAY_BUFFER, 0); //////////////////// // fill the texture part of the sectors texture = (PIELIGHT *)malloc(sizeof(PIELIGHT)*xSectors*ySectors*(sectorSize+1)*(sectorSize+1)*2*numGroundTypes); textureIndex = (GLuint *)malloc(sizeof(GLuint)*xSectors*ySectors*sectorSize*sectorSize*12*numGroundTypes); textureSize = 0; textureIndexSize = 0; for (layer = 0; layer < numGroundTypes; layer++) { for (x = 0; x < xSectors; x++) { for (y = 0; y < ySectors; y++) { if (layer == 0) { sectors[x*ySectors + y].textureOffset = (int *)malloc(sizeof(int)*numGroundTypes); sectors[x*ySectors + y].textureSize = (int *)malloc(sizeof(int)*numGroundTypes); sectors[x*ySectors + y].textureIndexOffset = (int *)malloc(sizeof(int)*numGroundTypes); sectors[x*ySectors + y].textureIndexSize = (int *)malloc(sizeof(int)*numGroundTypes); } sectors[x*ySectors + y].textureOffset[layer] = textureSize; sectors[x*ySectors + y].textureSize[layer] = 0; sectors[x*ySectors + y].textureIndexOffset[layer] = textureIndexSize; sectors[x*ySectors + y].textureIndexSize[layer] = 0; //debug(LOG_WARNING, "offset when filling %i: %i", layer, xSectors*ySectors*(sectorSize+1)*(sectorSize+1)*2*layer); for (i = 0; i < sectorSize+1; i++) { for (j = 0; j < sectorSize+1; j++) { bool draw = false; bool off_map; // set transparency for (a=0;a<2;a++) { for(b=0;b<2;b++) { absX = x*sectorSize+i+a; absY = y*sectorSize+j+b; colour[a][b].rgba = 0x00FFFFFF; // transparent // extend the terrain type for the bottom and left edges of the map off_map = false; if (absX == mapWidth) { off_map = true; absX--; } if (absY == mapHeight) { off_map = true; absY--; } if (absX < 0 || absY < 0 || absX >= mapWidth || absY >= mapHeight) { // not on the map, so don't draw continue; } if (mapTile(absX,absY)->ground == layer) { colour[a][b].rgba = 0xFFFFFFFF; if (!off_map) { // if this point lies on the edge is may not force this tile to be drawn // otherwise this will give a bright line when fog is enabled draw = true; } } } } texture[xSectors*ySectors*(sectorSize+1)*(sectorSize+1)*2*layer+((x*ySectors+y)*(sectorSize+1)*(sectorSize+1)*2 + (i*(sectorSize+1)+j)*2)].rgba = colour[0][0].rgba; averageColour(¢erColour, colour[0][0], colour[0][1], colour[1][0], colour[1][1]); texture[xSectors*ySectors*(sectorSize+1)*(sectorSize+1)*2*layer+((x*ySectors+y)*(sectorSize+1)*(sectorSize+1)*2 + (i*(sectorSize+1)+j)*2+1)].rgba = centerColour.rgba; textureSize += 2; if ((draw) && i < sectorSize && j < sectorSize) { textureIndex[textureIndexSize+0] = q(i ,j ,1); textureIndex[textureIndexSize+1] = q(i ,j ,0); textureIndex[textureIndexSize+2] = q(i+1,j ,0); textureIndex[textureIndexSize+3] = q(i ,j ,1); textureIndex[textureIndexSize+4] = q(i ,j+1,0); textureIndex[textureIndexSize+5] = q(i ,j ,0); textureIndex[textureIndexSize+6] = q(i ,j ,1); textureIndex[textureIndexSize+7] = q(i+1,j+1,0); textureIndex[textureIndexSize+8] = q(i ,j+1,0); textureIndex[textureIndexSize+9] = q(i ,j ,1); textureIndex[textureIndexSize+10] = q(i+1,j ,0); textureIndex[textureIndexSize+11] = q(i+1,j+1,0); textureIndexSize += 12; } } } sectors[x*ySectors + y].textureSize[layer] = textureSize - sectors[x*ySectors + y].textureOffset[layer]; sectors[x*ySectors + y].textureIndexSize[layer] = textureIndexSize - sectors[x*ySectors + y].textureIndexOffset[layer]; } } } glGenBuffers(1, &textureVBO); glError(); glBindBuffer(GL_ARRAY_BUFFER, textureVBO); glError(); glBufferData(GL_ARRAY_BUFFER, sizeof(PIELIGHT)*xSectors*ySectors*(sectorSize+1)*(sectorSize+1)*2*numGroundTypes, texture, GL_STATIC_DRAW); glError(); free(texture); glGenBuffers(1, &textureIndexVBO); glError(); glBindBuffer(GL_ARRAY_BUFFER, textureIndexVBO); glError(); glBufferData(GL_ARRAY_BUFFER, sizeof(GLuint)*textureIndexSize, textureIndex, GL_STATIC_DRAW); glError(); free(textureIndex); glBindBuffer(GL_ARRAY_BUFFER, 0); // and finally the decals decaldata = (DecalVertex *)malloc(sizeof(DecalVertex)*mapWidth*mapHeight*12); decalSize = 0; for (x = 0; x < xSectors; x++) { for (y = 0; y < ySectors; y++) { sectors[x*ySectors + y].decalOffset = decalSize; sectors[x*ySectors + y].decalSize = 0; setSectorDecals(x, y, decaldata, &decalSize); sectors[x*ySectors + y].decalSize = decalSize - sectors[x*ySectors + y].decalOffset; } } debug(LOG_TERRAIN, "%i decals found", decalSize/12); glGenBuffers(1, &decalVBO); glError(); glBindBuffer(GL_ARRAY_BUFFER, decalVBO); glError(); glBufferData(GL_ARRAY_BUFFER, sizeof(DecalVertex)*decalSize, decaldata, GL_STATIC_DRAW); glError(); free(decaldata); glBindBuffer(GL_ARRAY_BUFFER, 0); lightmap_tex_num = 0; lightmapLastUpdate = 0; lightmapWidth = 1; lightmapHeight = 1; // determine the smallest power-of-two size we can use for the lightmap while (mapWidth > (lightmapWidth <<= 1)) {} while (mapHeight > (lightmapHeight <<= 1)) {} debug(LOG_TERRAIN, "the size of the map is %ix%i", mapWidth, mapHeight); debug(LOG_TERRAIN, "lightmap texture size is %ix%i", lightmapWidth, lightmapHeight); // Prepare the lightmap pixmap and texture lightmapPixmap = (GLubyte *)calloc(lightmapWidth * lightmapHeight, 3 * sizeof(GLubyte)); if (lightmapPixmap == NULL) { debug(LOG_FATAL, "Out of memory!"); abort(); return false; } glGenTextures(1, &lightmap_tex_num); glBindTexture(GL_TEXTURE_2D, lightmap_tex_num); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, lightmapWidth, lightmapHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, lightmapPixmap); terrainInitalised = true; glBindBuffer(GL_ARRAY_BUFFER, 0); // HACK Must unbind GL_ARRAY_BUFFER (in this function, at least), otherwise text rendering may mysteriously crash. return true; }
bool CvArea::isLake() const { return (isWater() && (getNumTiles() <= GC.getLAKE_MAX_AREA_SIZE())); }