gba-x3dtest

annotate src/polyfill.c @ 5:850be43b3135

sdl version
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 16 Jun 2014 22:01:45 +0300
parents
children 73b5f2e5d18a
rev   line source
nuclear@5 1 #include "config.h"
nuclear@5 2 #include <string.h>
nuclear@5 3 #include "polyfill.h"
nuclear@5 4 #include "fixed.h"
nuclear@5 5 #include "gbasys.h"
nuclear@5 6
nuclear@5 7 static void fill_scanline(int y, int x0, int x1, uint16_t color);
nuclear@5 8
nuclear@5 9 void draw_poly(int num, const pvec3 *verts, uint16_t color)
nuclear@5 10 {
nuclear@5 11 int i, topidx = 0, botidx = 0;
nuclear@5 12 int lidx[2], ridx[2];
nuclear@5 13 int32_t y, topy, boty;
nuclear@5 14 int32_t ldy, rdy, ldxdy, rdxdy;
nuclear@5 15 int32_t lx, rx;
nuclear@5 16 int start, end;
nuclear@5 17
nuclear@5 18 topy = boty = verts[0].y;
nuclear@5 19 for(i=1; i<num; i++) {
nuclear@5 20 int32_t y = verts[i].y;
nuclear@5 21 if(y < topy) {
nuclear@5 22 topy = y;
nuclear@5 23 topidx = i;
nuclear@5 24 }
nuclear@5 25 if(y > boty) {
nuclear@5 26 boty = y;
nuclear@5 27 botidx = i;
nuclear@5 28 }
nuclear@5 29 }
nuclear@5 30
nuclear@5 31 lidx[0] = ridx[0] = topidx;
nuclear@5 32 lidx[1] = topidx ? topidx - 1 : num - 1;
nuclear@5 33 ridx[1] = (topidx + 1) % num;
nuclear@5 34
nuclear@5 35 if(ridx[1] < lidx[1]) {
nuclear@5 36 return; /* backface (CCW) */
nuclear@5 37 }
nuclear@5 38
nuclear@5 39 lx = rx = verts[lidx[0]].x;
nuclear@5 40
nuclear@5 41 ldy = verts[lidx[1]].y - verts[lidx[0]].y;
nuclear@5 42 ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
nuclear@5 43
nuclear@5 44 rdy = verts[ridx[1]].y - verts[ridx[1]].y;
nuclear@5 45 rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
nuclear@5 46
nuclear@5 47 start = topy >> 16;
nuclear@5 48 end = boty >> 16;
nuclear@5 49
nuclear@5 50 y = topy;
nuclear@5 51 for(i=start; i<end; i++) {
nuclear@5 52 unsigned short x0, x1;
nuclear@5 53
nuclear@5 54 x0 = lx < 0 ? 0 : (lx >> 16);
nuclear@5 55 x1 = rx >= WIDTH ? WIDTH - 1 : (rx >> 16);
nuclear@5 56
nuclear@5 57 fill_scanline(i, x0, x1, color);
nuclear@5 58
nuclear@5 59 if(y >= verts[lidx[1]].y) {
nuclear@5 60 lidx[0] = lidx[1];
nuclear@5 61 lidx[1] = lidx[1] ? lidx[1] - 1 : num - 1;
nuclear@5 62 ldy = verts[lidx[1]].y - verts[lidx[0]].y;
nuclear@5 63 if(ldy < 0) {
nuclear@5 64 break;
nuclear@5 65 }
nuclear@5 66 ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
nuclear@5 67 }
nuclear@5 68 if(y >= verts[ridx[1]].y) {
nuclear@5 69 ridx[0] = ridx[1];
nuclear@5 70 ridx[1] = (ridx[1] + 1) % num;
nuclear@5 71 rdy = verts[ridx[1]].y - verts[ridx[0]].y;
nuclear@5 72 if(rdy < 0) {
nuclear@5 73 break;
nuclear@5 74 }
nuclear@5 75 rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
nuclear@5 76 }
nuclear@5 77
nuclear@5 78 lx += ldxdy;
nuclear@5 79 rx += rdxdy;
nuclear@5 80 }
nuclear@5 81 }
nuclear@5 82
nuclear@5 83 static void fill_scanline(int y, int x0, int x1, uint16_t color)
nuclear@5 84 {
nuclear@5 85 int i;
nuclear@5 86 uint16_t *pixels = (uint16_t*)back_buffer->pixels + y * WIDTH + x0;
nuclear@5 87
nuclear@5 88 for(i=x0; i<x1; i++) {
nuclear@5 89 *pixels++ = color;
nuclear@5 90 }
nuclear@5 91 }