/** * zeichnet den Kartenausschnitt. * * @author OLiver * @author FloSoft */ void TerrainRenderer::Draw(GameWorldView * gwv, unsigned int *water) { assert(gl_vertices); assert(borders); /* if ((gwv->GetXOffset() == gwv->terrain_last_xoffset) && (gwv->GetYOffset() == gwv->terrain_last_yoffset) && (gwv->terrain_list != 0) && (GAMECLIENT.GetGlobalAnimation(4, 5, 4, 0) == gwv->terrain_last_global_animation)) { glCallList(gwv->terrain_list); *water = gwv->terrain_last_water; return; } gwv->terrain_last_xoffset = gwv->GetXOffset(); gwv->terrain_last_yoffset = gwv->GetYOffset(); gwv->terrain_last_global_animation = GAMECLIENT.GetGlobalAnimation(4, 5, 4, 0); if (gwv->terrain_list == 0) gwv->terrain_list = glGenLists(1); glNewList(gwv->terrain_list, GL_COMPILE_AND_EXECUTE);*/ PrepareWays(gwv); // nach Texture in Listen sortieren std::list<MapTile> sorted_textures[16]; std::list<BorderTile> sorted_borders[5]; int lastxo = 0, lastyo = 0; int xo, yo; unsigned short tx,ty; unsigned int offset = width * height * 2; // Beim zeichnen immer nur beginnen, wo man auch was sieht for(int y = gwv->GetFirstY(); y < gwv->GetLastY(); ++y) { unsigned char last = 255; unsigned char last_border = 255; for(int x = gwv->GetFirstX(); x < gwv->GetLastX(); ++x) { ConvertCoords(x, y, tx, ty, &xo, &yo); unsigned char t = gwv->GetGameWorldViewer()->GetNode(tx,ty).t1; if(xo != lastxo || yo != lastyo) last = 255; if(t == last) ++sorted_textures[t].back().count; else { MapTile tmp = {tx * 2, ty, 1, xo, yo}; sorted_textures[t].push_back(tmp); } last = t; t = gwv->GetGameWorldViewer()->GetNode(tx,ty).t2; if(t == last) ++sorted_textures[t].back().count; else { MapTile tmp = {tx * 2 + 1, ty, 1, xo, yo}; sorted_textures[t].push_back(tmp); } last = t; unsigned char tiles[6] = { borders[ty * width + tx].left_right[0], borders[ty * width + tx].left_right[1], borders[ty * width + tx].right_left[0], borders[ty * width + tx].right_left[1], borders[ty * width + tx].top_down[0], borders[ty * width + tx].top_down[1], }; unsigned int offsets[6] = { borders[ty * width + tx].left_right_offset[0], borders[ty * width + tx].left_right_offset[1], borders[ty * width + tx].right_left_offset[0], borders[ty * width + tx].right_left_offset[1], borders[ty * width + tx].top_down_offset[0], borders[ty * width + tx].top_down_offset[1], }; for(unsigned char i = 0; i < 6; ++i) { if(tiles[i]) { if(tiles[i] == last_border) ++sorted_borders[last_border-1].back().count; else { last_border = tiles[i]; BorderTile tmp = { offsets[i], 1, xo, yo}; sorted_borders[last_border-1].push_back(tmp); } ++offset; } } PrepareWaysPoint(gwv, tx, ty, xo, yo); lastxo = xo; lastyo = yo; } } if (water) { unsigned water_count = 0; for(std::list<MapTile>::iterator it = sorted_textures[TT_WATER].begin(); it != sorted_textures[TT_WATER].end(); ++it) { water_count += it->count; } if( (gwv->GetLastX() - gwv->GetFirstX()) && (gwv->GetLastY() - gwv->GetFirstY()) ) *water = 50 * water_count / ( (gwv->GetLastX() - gwv->GetFirstX()) * (gwv->GetLastY() - gwv->GetFirstY()) ); else *water = 0; } lastxo = 0; lastyo = 0; if(SETTINGS.video.vbo) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_vertices); glVertexPointer(2, GL_FLOAT, 0, NULL); glBindBufferARB(GL_ARRAY_BUFFER_ARB,vbo_texcoords); glTexCoordPointer(2, GL_FLOAT, 0, NULL); glBindBufferARB(GL_ARRAY_BUFFER_ARB,vbo_colors); glColorPointer(3, GL_FLOAT, 0, NULL); } else { glVertexPointer(2, GL_FLOAT, 0, gl_vertices); glTexCoordPointer(2, GL_FLOAT, 0, gl_texcoords); glColorPointer(3, GL_FLOAT, 0, gl_colors); } // Arrays aktivieren glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); // Modulate2x glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); // Verschieben gemäß x und y offset glTranslatef( float(-gwv->GetXOffset()), float(-gwv->GetYOffset()), 0.0f); // Alphablending aus glDisable(GL_BLEND); for(unsigned char i = 0; i < 16; ++i) { if(sorted_textures[i].size()) { switch(i) { case TT_WATER: VideoDriverWrapper::inst().BindTexture(GetImage(water, GAMECLIENT.GetGlobalAnimation(8, 5, 2, 0))->GetTexture()); break; case TT_LAVA: VideoDriverWrapper::inst().BindTexture(GetImage(lava, GAMECLIENT.GetGlobalAnimation(4, 5, 4, 0))->GetTexture()); break; default: VideoDriverWrapper::inst().BindTexture(GetImage(textures, i)->GetTexture()); } for(std::list<MapTile>::iterator it = sorted_textures[i].begin(); it != sorted_textures[i].end(); ++it) { if(it->xo != lastxo || it->yo != lastyo) { glTranslatef( float(it->xo - lastxo), float(it->yo - lastyo), 0.0f); lastxo = it->xo; lastyo = it->yo; } glDrawArrays(GL_TRIANGLES, it->y * width * 3 * 2 + it->x * 3, it->count * 3); } } } glEnable(GL_BLEND); glLoadIdentity(); glTranslatef( float(-gwv->GetXOffset()), float(-gwv->GetYOffset()), 0.0f); lastxo = 0; lastyo = 0; for(unsigned short i = 0;i<5;++i) { if(sorted_borders[i].size()) { VideoDriverWrapper::inst().BindTexture(GetImage(borders, i)->GetTexture()); for(std::list<BorderTile>::iterator it = sorted_borders[i].begin(); it != sorted_borders[i].end(); ++it) { if(it->xo != lastxo || it->yo != lastyo) { glTranslatef( float(it->xo - lastxo), float(it->yo - lastyo), 0.0f); lastxo = it->xo; lastyo = it->yo; } glDrawArrays(GL_TRIANGLES, it->offset * 3, it->count * 3); } } } glLoadIdentity(); DrawWays(gwv); // Wieder zurück ins normale modulate glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); /* glEndList(); gwv->terrain_last_water = *water;*/ }
/** * zeichnet den Kartenausschnitt. * * @author OLiver * @author FloSoft */ void TerrainRenderer::Draw(const GameWorldView& gwv, unsigned int* water) { assert(!gl_vertices.empty()); assert(!borders.empty()); /* if ((gwv.GetXOffset() == gwv.terrain_last_xoffset) && (gwv.GetYOffset() == gwv.terrain_last_yoffset) && (gwv.terrain_list != 0) && (GAMECLIENT.GetGlobalAnimation(4, 5, 4, 0) == gwv.terrain_last_global_animation)) { glCallList(gwv.terrain_list); *water = gwv.terrain_last_water; return; } gwv.terrain_last_xoffset = gwv.GetXOffset(); gwv.terrain_last_yoffset = gwv.GetYOffset(); gwv.terrain_last_global_animation = GAMECLIENT.GetGlobalAnimation(4, 5, 4, 0); if (gwv.terrain_list == 0) gwv.terrain_list = glGenLists(1); glNewList(gwv.terrain_list, GL_COMPILE_AND_EXECUTE);*/ // nach Texture in Listen sortieren boost::array< std::vector<MapTile>, TT_COUNT> sorted_textures; boost::array< std::vector<BorderTile>, 5> sorted_borders; PreparedRoads sorted_roads; Point<int> lastOffset(0, 0); // Beim zeichnen immer nur beginnen, wo man auch was sieht for(int y = gwv.GetFirstPt().y; y < gwv.GetLastPt().y; ++y) { unsigned char lastTerrain = 255; unsigned char lastBorder = 255; for(int x = gwv.GetFirstPt().x; x < gwv.GetLastPt().x; ++x) { Point<int> posOffset; MapPoint tP = ConvertCoords(Point<int>(x, y), &posOffset); TerrainType t = gwv.GetGameWorldViewer().GetNode(tP).t1; if(posOffset != lastOffset) lastTerrain = 255; if(t == lastTerrain && tP != MapPoint(0, 0)) ++sorted_textures[t].back().count; else { MapTile tmp(GetTriangleIdx(tP), posOffset); sorted_textures[t].push_back(tmp); lastTerrain = t; } t = gwv.GetGameWorldViewer().GetNode(tP).t2; if(t == lastTerrain) ++sorted_textures[t].back().count; else { MapTile tmp(GetTriangleIdx(tP) + 1, posOffset); sorted_textures[t].push_back(tmp); } lastTerrain = t; const Borders& curBorders = borders[GetVertexIdx(tP)]; boost::array<unsigned char, 6> tiles = {{ curBorders.left_right[0], curBorders.left_right[1], curBorders.right_left[0], curBorders.right_left[1], curBorders.top_down[0], curBorders.top_down[1] }}; // Offsets into gl_* arrays boost::array<unsigned, 6> offsets = {{ curBorders.left_right_offset[0], curBorders.left_right_offset[1], curBorders.right_left_offset[0], curBorders.right_left_offset[1], curBorders.top_down_offset[0], curBorders.top_down_offset[1] }}; for(unsigned char i = 0; i < 6; ++i) { if(!tiles[i]) continue; if(tiles[i] == lastBorder) { BorderTile& curTile = sorted_borders[lastBorder - 1].back(); // Check that we did not wrap around the map and the expected offset matches if(curTile.tileOffset + curTile.count == offsets[i]) { ++curTile.count; continue; } } lastBorder = tiles[i]; BorderTile tmp(offsets[i], posOffset); sorted_borders[lastBorder - 1].push_back(tmp); } PrepareWaysPoint(sorted_roads, gwv, tP, posOffset); lastOffset = posOffset; } } if (water) { unsigned water_count = 0; for(unsigned char t = 0; t < TT_COUNT; ++t){ if(!TerrainData::IsWater(TerrainType(t))) continue; for(std::vector<MapTile>::iterator it = sorted_textures[t].begin(); it != sorted_textures[t].end(); ++it) { water_count += it->count; } } PointI diff = gwv.GetLastPt() - gwv.GetFirstPt(); if( diff.x && diff.y ) *water = 50 * water_count / ( diff.x * diff.y ); else *water = 0; } lastOffset = PointI(0, 0); if(vboBuffersUsed) { glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_vertices); glVertexPointer(2, GL_FLOAT, 0, NULL); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_texcoords); glTexCoordPointer(2, GL_FLOAT, 0, NULL); glBindBufferARB(GL_ARRAY_BUFFER_ARB, vbo_colors); glColorPointer(3, GL_FLOAT, 0, NULL); } else { glVertexPointer(2, GL_FLOAT, 0, &gl_vertices.front()); glTexCoordPointer(2, GL_FLOAT, 0, &gl_texcoords.front()); glColorPointer(3, GL_FLOAT, 0, &gl_colors.front()); } // Arrays aktivieren glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); // Modulate2x glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); glTexEnvf(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, 2.0f); // Verschieben gem#ß x und y offset glTranslatef( float(-gwv.GetXOffset()), float(-gwv.GetYOffset()), 0.0f); // Alphablending aus glDisable(GL_BLEND); for(unsigned char t = 0; t < TT_COUNT; ++t) { if(sorted_textures[t].empty()) continue; unsigned animationFrame; TerrainType tt = TerrainType(t); if(TerrainData::IsLava(tt)) animationFrame = GAMECLIENT.GetGlobalAnimation(TerrainData::GetFrameCount(tt), 5, 4, 0); else if(TerrainData::IsWater(tt)) animationFrame = GAMECLIENT.GetGlobalAnimation(TerrainData::GetFrameCount(tt), 5, 2, 0); else animationFrame = 0; VIDEODRIVER.BindTexture(LOADER.GetTerrainTexture(tt, animationFrame).GetTexture()); for(std::vector<MapTile>::iterator it = sorted_textures[t].begin(); it != sorted_textures[t].end(); ++it) { if(it->posOffset != lastOffset) { PointI trans = it->posOffset - lastOffset; glTranslatef( float(trans.x), float(trans.y), 0.0f); lastOffset = it->posOffset; } assert(it->tileOffset + it->count <= width * height * 2u); glDrawArrays(GL_TRIANGLES, it->tileOffset * 3, it->count * 3); // Arguments are in Elements. 1 triangle has 3 values } } glEnable(GL_BLEND); glLoadIdentity(); glTranslatef( float(-gwv.GetXOffset()), float(-gwv.GetYOffset()), 0.0f); lastOffset = PointI(0, 0); for(unsigned short i = 0; i < 5; ++i) { if(sorted_borders[i].empty()) continue; VIDEODRIVER.BindTexture(GetImage(borders, i)->GetTexture()); for(std::vector<BorderTile>::iterator it = sorted_borders[i].begin(); it != sorted_borders[i].end(); ++it) { if(it->posOffset != lastOffset) { PointI trans = it->posOffset - lastOffset; glTranslatef( float(trans.x), float(trans.y), 0.0f); lastOffset = it->posOffset; } assert(it->tileOffset + it->count <= gl_vertices.size()); glDrawArrays(GL_TRIANGLES, it->tileOffset * 3, it->count * 3); // Arguments are in Elements. 1 triangle has 3 values } } glLoadIdentity(); DrawWays(sorted_roads); // Wieder zurück ins normale modulate glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); }