/**
 *  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;*/
}
Example #2
0
/**
 *  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);
}