#include #include #include "renderer.h" #include "system/error.h" #include "system/lt.h" int draw_triangle(SDL_Renderer *render, Triangle t) { assert(render); if (SDL_RenderDrawLine(render, (int) roundf(t.p1.x), (int) roundf(t.p1.y), (int) roundf(t.p2.x), (int) roundf(t.p2.y)) < 0) { throw_error(ERROR_TYPE_SDL2); return -1; } if (SDL_RenderDrawLine(render, (int) roundf(t.p2.x), (int) roundf(t.p2.y), (int) roundf(t.p3.x), (int) roundf(t.p3.y)) < 0) { throw_error(ERROR_TYPE_SDL2); return -1; } if (SDL_RenderDrawLine(render, (int) roundf(t.p3.x), (int) roundf(t.p3.y), (int) roundf(t.p1.x), (int) roundf(t.p1.y)) < 0) { throw_error(ERROR_TYPE_SDL2); return -1; } return 0; } static int fill_bottom_flat_triangle(SDL_Renderer *render, Triangle t) { assert(render); const float invslope1 = (t.p2.x - t.p1.x) / (t.p2.y - t.p1.y); const float invslope2 = (t.p3.x - t.p1.x) / (t.p3.y - t.p1.y); const int y0 = (int) roundf(t.p1.y); const int y1 = (int) roundf(t.p2.y); float curx1 = t.p1.x; float curx2 = t.p1.x; for (int scanline = y0; scanline < y1; scanline++) { if (SDL_RenderDrawLine(render, (int) roundf(curx1), scanline, (int) roundf(curx2), scanline) < 0) { return -1; } curx1 += invslope1; curx2 += invslope2; } return 0; } static int fill_top_flat_triangle(SDL_Renderer *render, Triangle t) { assert(render); const float invslope1 = (t.p3.x - t.p1.x) / (t.p3.y - t.p1.y); const float invslope2 = (t.p3.x - t.p2.x) / (t.p3.y - t.p2.y); const int y0 = (int) roundf(t.p3.y); const int y1 = (int) roundf(t.p1.y); float curx1 = t.p3.x; float curx2 = t.p3.x; for (int scanline = y0; scanline > y1; --scanline) { if (SDL_RenderDrawLine(render, (int) roundf(curx1), scanline, (int) roundf(curx2), scanline) < 0) { return -1; } curx1 -= invslope1; curx2 -= invslope2; } return 0; } int fill_triangle(SDL_Renderer *render, Triangle t) { t = triangle_sorted_by_y(t); if (fabs(t.p2.y - t.p3.y) < 1e-6) { if (fill_bottom_flat_triangle(render, t) < 0) { return -1; } } else if (fabs(t.p1.y - t.p2.y) < 1e-6) { if (fill_top_flat_triangle(render, t) < 0) { return -1; } } else { const Point p4 = vec(t.p1.x + ((t.p2.y - t.p1.y) / (t.p3.y - t.p1.y)) * (t.p3.x - t.p1.x), t.p2.y); if (fill_bottom_flat_triangle(render, triangle(t.p1, t.p2, p4)) < 0) { return -1; } if (fill_top_flat_triangle(render, triangle(t.p2, p4, t.p3)) < 0) { return -1; } if (SDL_RenderDrawLine(render, (int) roundf(t.p2.x), (int) roundf(t.p2.y), (int) roundf(p4.x), (int) roundf(p4.y)) < 0) { return -1; } } return 0; } int fill_rect(SDL_Renderer *render, Rect r, Color c) { const SDL_Rect sdl_rect = rect_for_sdl(r); const SDL_Color sdl_color = color_for_sdl(c); if (SDL_SetRenderDrawColor( render, sdl_color.r, sdl_color.g, sdl_color.b, sdl_color.a) < 0) { throw_error(ERROR_TYPE_SDL2); return -1; } if (SDL_RenderFillRect(render, &sdl_rect) < 0) { throw_error(ERROR_TYPE_SDL2); return -1; } return 0; } /* * Return the pixel value at (x, y) * NOTE: The surface must be locked before calling this! */ Uint32 getpixel(SDL_Surface *surface, int x, int y) { int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to retrieve */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch(bpp) { case 1: return *p; case 2: return *(Uint16 *)p; case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN) return (Uint32) p[0] << 16 | (Uint32) p[1] << 8 | (Uint32) p[2]; else return (Uint32) p[0] | (Uint32) p[1] << 8 | (Uint32) p[2] << 16; case 4: return *(Uint32 *)p; default: return 0; /* shouldn't happen, but avoids warnings */ } } /* * Set the pixel at (x, y) to the given value * NOTE: The surface must be locked before calling this! */ void putpixel(SDL_Surface *surface, int x, int y, Uint32 pixel) { int bpp = surface->format->BytesPerPixel; /* Here p is the address to the pixel we want to set */ Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp; switch(bpp) { case 1: *(Uint32*) p = pixel; break; case 2: *(Uint16 *)p = (Uint16) pixel; break; case 3: if(SDL_BYTEORDER == SDL_BIG_ENDIAN) { p[0] = (pixel >> 16) & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = pixel & 0xff; } else { p[0] = pixel & 0xff; p[1] = (pixel >> 8) & 0xff; p[2] = (pixel >> 16) & 0xff; } break; case 4: *(Uint32 *)p = pixel; break; } }