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