void DrawPolygon(SDL_Surface* buf, Vertex2f ver[3])
{
int order[3];
// Starting and ending points of the scanlines
float x0 = 0, x1 = 0;
float xl = x0, xr = x1;
float z0 = 0, z1 = 0;
float zl = z0, zr = z1;
// Slopes
float d0 = 0;
float d1 = 0;
// Polygon parts to draw flags
bool drawHalf1 = true;
bool drawHalf2 = true;
// Sort the vertices
// find the lowest Y
if (ver[0].y < ver[1].y)
{
if (ver[0].y < ver[2].y)
{
order[0] = 0;
}
else
{
order[0] = 2;
}
}
else
{
if (ver[1].y < ver[2].y)
{
order[0] = 1;
}
else
{
order[0] = 2;
}
}
// find the highest Y
if (ver[0].y > ver[1].y)
{
if (ver[0].y > ver[2].y)
{
order[2] = 0;
}
else
{
order[2] = 2;
}
}
else
{
if (ver[1].y > ver[2].y)
{
order[2] = 1;
}
else
{
order[2] = 2;
}
}
// and the middle one is a matter of deduction
order[1] = 3 - (order[0] + order[2]);
// Check which parts of polygon to draw
// Should we render the polygon at all?
if(ver[order[0]].y - ver[order[2]].y == 0.0f) // The polygon has no height so we don't render it
{
return;
}
else if(ver[order[1]].y - ver[order[2]].y == 0.0f) // The polygon has only the frist half
{
drawHalf2 = false;
}
else if(ver[order[0]].y - ver[order[1]].y == 0.0f) // The polygon has only the second half
{
drawHalf1 = false;
}
// slopes
d1 = (ver[order[2]].x - ver[order[0]].x) / (ver[order[2]].y - ver[order[0]].y);
// Draw the first half of the polygon
if(drawHalf1)
{
d0 = (ver[order[1]].x - ver[order[0]].x) / (ver[order[1]].y - ver[order[0]].y);
x0 = ver[order[0]].x;
x1 = ver[order[0]].x;
for(float y = ver[order[0]].y; y < ver[order[1]].y; ++y)
{
z0 = ver[order[0]].z - (ver[order[0]].z - ver[order[1]].z)*((ver[order[0]].y - y) / (ver[order[0]].y - ver[order[1]].y));
z1 = ver[order[0]].z - (ver[order[0]].z - ver[order[2]].z)*((ver[order[0]].y - y) / (ver[order[0]].y - ver[order[2]].y));
// x sorting
if(x0 < x1) { xl = x0; xr = x1; zl = z0; zr = z1; } else
{ xl = x1; xr = x0; zl = z1; zr = z0; }
//fastline(buf, (int)xl, (int)y, (int)xr, (int)y, ver[order[0]].color);
DrawSpan(buf, (int)xl, (int)xr, (int)y, zl, zr, ver[order[0]].color);
/*
for(float x = xl; x < xr; ++x)
putpixel(buf, (int)x, (int)y, ver[order[0]].color);
*/
x0 += d0;
x1 += d1;
}
}
if(drawHalf2)
{
d0 = (ver[order[2]].x - ver[order[1]].x) / (ver[order[2]].y - ver[order[1]].y);
x0 = ver[order[2]].x;
x1 = ver[order[2]].x;
for(float y = ver[order[2]].y; y > ver[order[1]].y; --y)
{
z0 = ver[order[0]].z - (ver[order[0]].z - ver[order[1]].z)*((ver[order[0]].y - y) / (ver[order[0]].y - ver[order[1]].y));
z1 = ver[order[0]].z - (ver[order[0]].z - ver[order[2]].z)*((ver[order[0]].y - y) / (ver[order[0]].y - ver[order[2]].y));
// x sorting
if(x0 < x1) { xl = x0; xr = x1; zl = z0; zr = z1; } else
{ xl = x1; xr = x0; zl = z1; zr = z0; }
//fastline(buf, (int)xl, (int)y, (int)xr, (int)y, ver[order[0]].color);
DrawSpan(buf, (int)xl, (int)xr, (int)y, zl, zr, ver[order[0]].color);
/*
for(float x = xl; x < xr; ++x)
putpixel(buf, (int)x, (int)y, ver[order[0]].color);
*/
x0 -= d0;
x1 -= d1;
}
}
}
void DrawSpan(SDL_Surface* buf, int xa, int xb, int y, float za, float zb, int col)
{
float z = 0.0f;
for(int x = xa; x < xb; ++x)
{
z = (zb - (zb - za)*((xb - x)/(xb - xa)));
if( z >= depthBuffer->GetZBuffer(x, y) )
{
depthBuffer->SetZBuffer(x, y, z);
//if(buf->line[y][x]) buf->line[y][x] = col;
DrawPixel(buf, x, y, col);
}
}
}
void DrawPixel(SDL_Surface *screen, int x, int y, Uint32 color)
{
//Uint32 color = SDL_MapRGB(screen->format, R, G, B);
if(x > 0 && y > 0 && x < screen->w && y < screen->h)
switch (screen->format->BytesPerPixel)
{
case 1: // Assuming 8-bpp
{
Uint8 *bufp;
bufp = (Uint8 *)screen->pixels + y*screen->pitch + x;
*bufp = color;
}
break;
case 2: // Probably 15-bpp or 16-bpp
{
Uint16 *bufp;
bufp = (Uint16 *)screen->pixels + y*screen->pitch/2 + x;
*bufp = color;
}
break;
case 3: // Slow 24-bpp mode, usually not used
{
Uint8 *bufp;
bufp = (Uint8 *)screen->pixels + y*screen->pitch + x * 3;
if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
{
bufp[0] = color;
bufp[1] = color >> 8;
bufp[2] = color >> 16;
} else {
bufp[2] = color;
bufp[1] = color >> 8;
bufp[0] = color >> 16;
}
}
break;
case 4: // Probably 32-bpp
{
Uint32 *bufp;
bufp = (Uint32 *)screen->pixels + y*screen->pitch/4 + x;
*bufp = color;
}
break;
}
}