gba-x3dtest

diff src/polyfill.c @ 9:b0ed38f13261

working on the rasterizer
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 22 Jun 2014 05:16:10 +0300
parents fb0a0d6a8b52
children c398d834d64a
line diff
     1.1 --- a/src/polyfill.c	Thu Jun 19 05:53:46 2014 +0300
     1.2 +++ b/src/polyfill.c	Sun Jun 22 05:16:10 2014 +0300
     1.3 @@ -5,14 +5,18 @@
     1.4  #include "fixed.h"
     1.5  #include "gbasys.h"
     1.6  
     1.7 -static void fill_scanline(int y, int x0, int x1, uint16_t color);
     1.8 +#define VNEXT(x, n)		(((x) + 1) % (n))
     1.9 +#define VPREV(x, n)		((x) > 0 ? (x) - 1 : (n) - 1)
    1.10 +
    1.11 +static void fill_scanline_pal(int y, int x0, int x1, uint8_t color);
    1.12 +static void fill_scanline_rgb(int y, int x0, int x1, uint16_t color);
    1.13  
    1.14  void draw_poly(int num, const pvec3 *verts, uint16_t color)
    1.15  {
    1.16  	int i, topidx = 0, botidx = 0;
    1.17 -	int lidx[2], ridx[2];
    1.18 +	int lidx[2] = {-1, -1}, ridx[2] = {-1, -1};
    1.19  	int32_t y, topy, boty;
    1.20 -	int32_t ldy, rdy, ldxdy, rdxdy;
    1.21 +	int32_t ldy = 0, rdy = 0, ldxdy, rdxdy;
    1.22  	int32_t lx, rx;
    1.23  	int start, end;
    1.24  
    1.25 @@ -30,22 +34,46 @@
    1.26  	}
    1.27  
    1.28  	lidx[0] = ridx[0] = topidx;
    1.29 -	lidx[1] = topidx ? topidx - 1 : num - 1;
    1.30 -	ridx[1] = (topidx + 1) % num;
    1.31 +
    1.32 +	/* find starting left edge */
    1.33 +	lidx[1] = VPREV(lidx[0], num);
    1.34 +	ldy = verts[lidx[1]].y - verts[lidx[0]].y;
    1.35 +
    1.36 +	while(ldy == 0) {
    1.37 +		lidx[0] = lidx[1];
    1.38 +		lidx[1] = VPREV(lidx[1], num);
    1.39 +
    1.40 +		if(lidx[1] == topidx) {
    1.41 +			return;	/* degenerate */
    1.42 +		}
    1.43 +
    1.44 +		ldy = verts[lidx[1]].y - verts[lidx[0]].y;
    1.45 +	}
    1.46 +	lx = verts[lidx[0]].x;
    1.47 +	ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
    1.48 +
    1.49 +	/* find starting right edge */
    1.50 +	ridx[1] = VNEXT(ridx[0], num);
    1.51 +	rdy = verts[ridx[1]].y - verts[ridx[0]].y;
    1.52 +
    1.53 +	while(rdy == 0) {
    1.54 +		ridx[0] = ridx[1];
    1.55 +		ridx[1] = VNEXT(ridx[1], num);
    1.56 +
    1.57 +		if(ridx[1] == topidx) {
    1.58 +			return; /* degenerate */
    1.59 +		}
    1.60 +
    1.61 +		rdy = verts[ridx[1]].y - verts[ridx[0]].y;
    1.62 +	}
    1.63 +	rx = verts[ridx[0]].x;
    1.64 +	rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
    1.65 +
    1.66  
    1.67  	if(verts[ridx[1]].x < verts[lidx[1]].x) {
    1.68 -		return;	/* backface (CCW) */
    1.69 +		return;	/*  backface (CCW) */
    1.70  	}
    1.71  
    1.72 -	lx = rx = verts[lidx[0]].x;
    1.73 -
    1.74 -	/* TODO handle ldy == 0 or rdy == 0 */
    1.75 -	ldy = verts[lidx[1]].y - verts[lidx[0]].y;
    1.76 -	ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
    1.77 -
    1.78 -	rdy = verts[ridx[1]].y - verts[ridx[0]].y;
    1.79 -	rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
    1.80 -
    1.81  	start = topy >> 16;
    1.82  	end = boty >> 16;
    1.83  
    1.84 @@ -53,18 +81,12 @@
    1.85  
    1.86  	y = topy;
    1.87  	for(i=start; i<end; i++) {
    1.88 -		unsigned short x0, x1;
    1.89 -
    1.90 -		x0 = lx < 0 ? 0 : (lx >> 16);
    1.91 -		x1 = (rx >> 16) >= WIDTH ? WIDTH - 1 : (rx >> 16);
    1.92 -
    1.93 -		if(i >= 0 && x1 > x0) {
    1.94 -			fill_scanline(i, x0, x1, color);
    1.95 -		}
    1.96 +		short x0, x1;
    1.97  
    1.98  		if(y >= verts[lidx[1]].y) {
    1.99 +			lx = verts[lidx[1]].x;
   1.100  			lidx[0] = lidx[1];
   1.101 -			lidx[1] = lidx[1] ? lidx[1] - 1 : num - 1;
   1.102 +			lidx[1] = VPREV(lidx[1], num);
   1.103  			ldy = verts[lidx[1]].y - verts[lidx[0]].y;
   1.104  			if(ldy < 0) {
   1.105  				break;
   1.106 @@ -72,8 +94,9 @@
   1.107  			ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
   1.108  		}
   1.109  		if(y >= verts[ridx[1]].y) {
   1.110 +			rx = verts[ridx[1]].x;
   1.111  			ridx[0] = ridx[1];
   1.112 -			ridx[1] = (ridx[1] + 1) % num;
   1.113 +			ridx[1] = VNEXT(ridx[1], num);
   1.114  			rdy = verts[ridx[1]].y - verts[ridx[0]].y;
   1.115  			if(rdy < 0) {
   1.116  				break;
   1.117 @@ -81,13 +104,58 @@
   1.118  			rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
   1.119  		}
   1.120  
   1.121 +		x0 = lx < 0 ? 0 : (lx >> 16);
   1.122 +		x1 = (rx >> 16) >= WIDTH ? WIDTH - 1 : (rx >> 16);
   1.123 +
   1.124 +		if(i >= 0 && x1 > x0) {
   1.125 +#ifdef PALMODE
   1.126 +			fill_scanline_pal(i, x0, x1, (uint8_t)color);
   1.127 +#else
   1.128 +			fill_scanline_rgb(i, x0, x1, color);
   1.129 +#endif
   1.130 +		}
   1.131 +
   1.132  		lx += ldxdy;
   1.133  		rx += rdxdy;
   1.134  		y += 65536;
   1.135  	}
   1.136  }
   1.137  
   1.138 -static void fill_scanline(int y, int x0, int x1, uint16_t color)
   1.139 +
   1.140 +static void fill_scanline_pal(int y, int x0, int x1, uint8_t color)
   1.141 +{
   1.142 +#if 1
   1.143 +	int i, num_pairs, num_pix = x1 - x0;
   1.144 +	uint16_t *pixels = (uint16_t*)back_buffer->pixels + (y * WIDTH + x0) / 2;
   1.145 +	uint16_t colpair = (uint16_t)color | ((uint16_t)color << 8);
   1.146 +
   1.147 +	if(x0 & 1) {
   1.148 +		uint16_t pix = *pixels & 0xff;
   1.149 +		*pixels++ = pix | ((uint16_t)color << 8);
   1.150 +		--num_pix;
   1.151 +	}
   1.152 +
   1.153 +	num_pairs = (num_pix & 0xfffe) / 2;
   1.154 +
   1.155 +	for(i=0; i<num_pairs; i++) {
   1.156 +		*pixels++ = colpair;
   1.157 +	}
   1.158 +
   1.159 +	if(num_pix & 1) {
   1.160 +		uint16_t pix = *pixels & 0xff00;
   1.161 +		*pixels = pix | color;
   1.162 +	}
   1.163 +#else
   1.164 +	int i;
   1.165 +	uint8_t *pixels = (uint8_t*)back_buffer->pixels + y * WIDTH + x0;
   1.166 +
   1.167 +	for(i=x0; i<x1; i++) {
   1.168 +		*pixels++ = color;
   1.169 +	}
   1.170 +#endif
   1.171 +}
   1.172 +
   1.173 +static void fill_scanline_rgb(int y, int x0, int x1, uint16_t color)
   1.174  {
   1.175  	int i;
   1.176  	uint16_t *pixels = (uint16_t*)back_buffer->pixels + y * WIDTH + x0;
   1.177 @@ -108,5 +176,14 @@
   1.178  		return;
   1.179  	}
   1.180  
   1.181 +#ifdef PALMODE
   1.182 +	pixels += (y * WIDTH + x) / 2;
   1.183 +	if(x & 1) {
   1.184 +		*pixels = (*pixels & 0xff) | (color << 8);
   1.185 +	} else {
   1.186 +		*pixels = (*pixels & 0xff00) | color;
   1.187 +	}
   1.188 +#else
   1.189  	pixels[y * WIDTH + x] = color;
   1.190 +#endif
   1.191  }