nuclear@5: #include "config.h" nuclear@5: #include nuclear@6: #include nuclear@5: #include "polyfill.h" nuclear@5: #include "fixed.h" nuclear@5: #include "gbasys.h" nuclear@5: nuclear@9: #define VNEXT(x, n) (((x) + 1) % (n)) nuclear@9: #define VPREV(x, n) ((x) > 0 ? (x) - 1 : (n) - 1) nuclear@9: nuclear@9: static void fill_scanline_pal(int y, int x0, int x1, uint8_t color); nuclear@9: static void fill_scanline_rgb(int y, int x0, int x1, uint16_t color); nuclear@5: nuclear@5: void draw_poly(int num, const pvec3 *verts, uint16_t color) nuclear@5: { nuclear@5: int i, topidx = 0, botidx = 0; nuclear@9: int lidx[2] = {-1, -1}, ridx[2] = {-1, -1}; nuclear@5: int32_t y, topy, boty; nuclear@9: int32_t ldy = 0, rdy = 0, ldxdy, rdxdy; nuclear@5: int32_t lx, rx; nuclear@5: int start, end; nuclear@5: nuclear@5: topy = boty = verts[0].y; nuclear@5: for(i=1; i boty) { nuclear@5: boty = y; nuclear@5: botidx = i; nuclear@5: } nuclear@5: } nuclear@5: nuclear@5: lidx[0] = ridx[0] = topidx; nuclear@9: nuclear@9: /* find starting left edge */ nuclear@9: lidx[1] = VPREV(lidx[0], num); nuclear@9: ldy = verts[lidx[1]].y - verts[lidx[0]].y; nuclear@9: nuclear@9: while(ldy == 0) { nuclear@9: lidx[0] = lidx[1]; nuclear@9: lidx[1] = VPREV(lidx[1], num); nuclear@9: nuclear@9: if(lidx[1] == topidx) { nuclear@9: return; /* degenerate */ nuclear@9: } nuclear@9: nuclear@9: ldy = verts[lidx[1]].y - verts[lidx[0]].y; nuclear@9: } nuclear@9: lx = verts[lidx[0]].x; nuclear@9: ldxdy = x16div(verts[lidx[1]].x - lx, ldy); nuclear@9: nuclear@9: /* find starting right edge */ nuclear@9: ridx[1] = VNEXT(ridx[0], num); nuclear@9: rdy = verts[ridx[1]].y - verts[ridx[0]].y; nuclear@9: nuclear@9: while(rdy == 0) { nuclear@9: ridx[0] = ridx[1]; nuclear@9: ridx[1] = VNEXT(ridx[1], num); nuclear@9: nuclear@9: if(ridx[1] == topidx) { nuclear@9: return; /* degenerate */ nuclear@9: } nuclear@9: nuclear@9: rdy = verts[ridx[1]].y - verts[ridx[0]].y; nuclear@9: } nuclear@9: rx = verts[ridx[0]].x; nuclear@9: rdxdy = x16div(verts[ridx[1]].x - rx, rdy); nuclear@9: nuclear@5: nuclear@6: if(verts[ridx[1]].x < verts[lidx[1]].x) { nuclear@9: return; /* backface (CCW) */ nuclear@5: } nuclear@5: nuclear@5: start = topy >> 16; nuclear@5: end = boty >> 16; nuclear@5: nuclear@6: if(end >= HEIGHT) end = HEIGHT - 1; nuclear@6: nuclear@5: y = topy; nuclear@5: for(i=start; i= verts[lidx[1]].y) { nuclear@9: lx = verts[lidx[1]].x; nuclear@5: lidx[0] = lidx[1]; nuclear@9: lidx[1] = VPREV(lidx[1], num); nuclear@5: ldy = verts[lidx[1]].y - verts[lidx[0]].y; nuclear@5: if(ldy < 0) { nuclear@5: break; nuclear@5: } nuclear@5: ldxdy = x16div(verts[lidx[1]].x - lx, ldy); nuclear@5: } nuclear@5: if(y >= verts[ridx[1]].y) { nuclear@9: rx = verts[ridx[1]].x; nuclear@5: ridx[0] = ridx[1]; nuclear@9: ridx[1] = VNEXT(ridx[1], num); nuclear@5: rdy = verts[ridx[1]].y - verts[ridx[0]].y; nuclear@5: if(rdy < 0) { nuclear@5: break; nuclear@5: } nuclear@5: rdxdy = x16div(verts[ridx[1]].x - rx, rdy); nuclear@5: } nuclear@5: nuclear@9: x0 = lx < 0 ? 0 : (lx >> 16); nuclear@9: x1 = (rx >> 16) >= WIDTH ? WIDTH - 1 : (rx >> 16); nuclear@9: nuclear@9: if(i >= 0 && x1 > x0) { nuclear@9: #ifdef PALMODE nuclear@9: fill_scanline_pal(i, x0, x1, (uint8_t)color); nuclear@9: #else nuclear@9: fill_scanline_rgb(i, x0, x1, color); nuclear@9: #endif nuclear@9: } nuclear@9: nuclear@5: lx += ldxdy; nuclear@5: rx += rdxdy; nuclear@6: y += 65536; nuclear@5: } nuclear@5: } nuclear@5: nuclear@9: nuclear@9: static void fill_scanline_pal(int y, int x0, int x1, uint8_t color) nuclear@9: { nuclear@9: #if 1 nuclear@9: int i, num_pairs, num_pix = x1 - x0; nuclear@9: uint16_t *pixels = (uint16_t*)back_buffer->pixels + (y * WIDTH + x0) / 2; nuclear@9: uint16_t colpair = (uint16_t)color | ((uint16_t)color << 8); nuclear@9: nuclear@9: if(x0 & 1) { nuclear@9: uint16_t pix = *pixels & 0xff; nuclear@9: *pixels++ = pix | ((uint16_t)color << 8); nuclear@9: --num_pix; nuclear@9: } nuclear@9: nuclear@9: num_pairs = (num_pix & 0xfffe) / 2; nuclear@9: nuclear@9: for(i=0; ipixels + y * WIDTH + x0; nuclear@9: nuclear@9: for(i=x0; ipixels + y * WIDTH + x0; nuclear@5: nuclear@5: for(i=x0; ix >> 16; nuclear@8: int y = v->y >> 16; nuclear@8: uint16_t *pixels = (uint16_t*)back_buffer->pixels; nuclear@8: nuclear@8: if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) { nuclear@8: return; nuclear@8: } nuclear@8: nuclear@9: #ifdef PALMODE nuclear@9: pixels += (y * WIDTH + x) / 2; nuclear@9: if(x & 1) { nuclear@9: *pixels = (*pixels & 0xff) | (color << 8); nuclear@9: } else { nuclear@9: *pixels = (*pixels & 0xff00) | color; nuclear@9: } nuclear@9: #else nuclear@8: pixels[y * WIDTH + x] = color; nuclear@9: #endif nuclear@8: }