rayzor

diff src/lines.c @ 9:70e332156d02

moving along
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 10 Apr 2014 02:31:31 +0300
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/lines.c	Thu Apr 10 02:31:31 2014 +0300
     1.3 @@ -0,0 +1,146 @@
     1.4 +#include "lines.h"
     1.5 +
     1.6 +enum {
     1.7 +	IN		= 0,
     1.8 +	LEFT	= 1,
     1.9 +	RIGHT	= 2,
    1.10 +	TOP		= 4,
    1.11 +	BOTTOM	= 8
    1.12 +};
    1.13 +
    1.14 +static int outcode(int x, int y, int minx, int miny, int maxx, int maxy)
    1.15 +{
    1.16 +	int code = 0;
    1.17 +
    1.18 +	if(x < minx) {
    1.19 +		code |= LEFT;
    1.20 +	} else if(x > maxx) {
    1.21 +		code |= RIGHT;
    1.22 +	}
    1.23 +	if(y < miny) {
    1.24 +		code |= TOP;
    1.25 +	} else if(y > maxy) {
    1.26 +		code |= BOTTOM;
    1.27 +	}
    1.28 +	return code;
    1.29 +}
    1.30 +
    1.31 +#define FIXMUL(a, b)	(((a) * (b)) >> 8)
    1.32 +#define FIXDIV(a, b)	(((a) << 8) / (b))
    1.33 +
    1.34 +#define LERP(a, b, t)	((a) + FIXMUL((b) - (a), (t)))
    1.35 +
    1.36 +int clip_line2d(int *x0, int *y0, int *x1, int *y1, const int *vp)
    1.37 +{
    1.38 +	int oc_out;
    1.39 +	int minx = vp[0];
    1.40 +	int miny = vp[1];
    1.41 +	int maxx = vp[0] + vp[2] - 1;
    1.42 +	int maxy = vp[1] + vp[3] - 1;
    1.43 +
    1.44 +	int oc0 = outcode(*x0, *y0, minx, miny, maxx, maxy);
    1.45 +	int oc1 = outcode(*x1, *y1, minx, miny, maxx, maxy);
    1.46 +
    1.47 +	int32_t fx0, fy0, fx1, fy1, fminx, fminy, fmaxx, fmaxy;
    1.48 +
    1.49 +	if(!(oc0 | oc1)) return 1;	/* both points are inside */
    1.50 +
    1.51 +	fx0 = *x0 << 8;
    1.52 +	fy0 = *y0 << 8;
    1.53 +	fx1 = *x1 << 8;
    1.54 +	fy1 = *y1 << 8;
    1.55 +	fminx = minx << 8;
    1.56 +	fminy = miny << 8;
    1.57 +	fmaxx = maxx << 8;
    1.58 +	fmaxy = maxy << 8;
    1.59 +
    1.60 +	for(;;) {
    1.61 +		int32_t x, y, t;
    1.62 +
    1.63 +		if(oc0 & oc1) return 0;		/* both have points with the same outbit, not visible */
    1.64 +		if(!(oc0 | oc1)) break;		/* both points are inside */
    1.65 +
    1.66 +		oc_out = oc0 ? oc0 : oc1;
    1.67 +
    1.68 +		if(oc_out & TOP) {
    1.69 +			t = FIXDIV(fminy - fy0, fy1 - fy0);
    1.70 +			x = LERP(fx0, fx1, t);
    1.71 +			y = fminy;
    1.72 +		} else if(oc_out & BOTTOM) {
    1.73 +			t = FIXDIV(fmaxy - fy0, fy1 - fy0);
    1.74 +			x = LERP(fx0, fx1, t);
    1.75 +			y = fmaxy;
    1.76 +		} else if(oc_out & LEFT) {
    1.77 +			t = FIXDIV(fminx - fx0, fx1 - fx0);
    1.78 +			x = fminx;
    1.79 +			y = LERP(fy0, fy1, t);
    1.80 +		} else if(oc_out & RIGHT) {
    1.81 +			t = FIXDIV(fmaxx - fx0, fx1 - fx0);
    1.82 +			x = fmaxx;
    1.83 +			y = LERP(fy0, fy1, t);
    1.84 +		}
    1.85 +
    1.86 +		if(oc_out == oc0) {
    1.87 +			fx0 = x;
    1.88 +			fy0 = y;
    1.89 +			oc0 = outcode(fx0 >> 8, fy0 >> 8, minx, miny, maxx, maxy);
    1.90 +		} else {
    1.91 +			fx1 = x;
    1.92 +			fy1 = y;
    1.93 +			oc1 = outcode(fx1 >> 8, fy1 >> 8, minx, miny, maxx, maxy);
    1.94 +		}
    1.95 +	}
    1.96 +
    1.97 +	*x0 = fx0 >> 8;
    1.98 +	*y0 = fy0 >> 8;
    1.99 +	*x1 = fx1 >> 8;
   1.100 +	*y1 = fy1 >> 8;
   1.101 +	return 1;
   1.102 +}
   1.103 +
   1.104 +void draw_line(uint32_t *fb, int fbwidth, uint32_t col, int x0, int y0, int x1, int y1)
   1.105 +{
   1.106 +	int i, dx, dy, x_inc, y_inc, error;
   1.107 +
   1.108 +	fb += y0 * fbwidth + x0;
   1.109 +
   1.110 +	dx = x1 - x0;
   1.111 +	dy = y1 - y0;
   1.112 +
   1.113 +	if(dx >= 0) {
   1.114 +		x_inc = 1;
   1.115 +	} else {
   1.116 +		x_inc = -1;
   1.117 +		dx = -dx;
   1.118 +	}
   1.119 +	if(dy >= 0) {
   1.120 +		y_inc = fbwidth;
   1.121 +	} else {
   1.122 +		y_inc = -fbwidth;
   1.123 +		dy = -dy;
   1.124 +	}
   1.125 +
   1.126 +	if(dx > dy) {
   1.127 +		error = dy * 2 - dx;
   1.128 +		for(i=0; i<=dx; i++) {
   1.129 +			*fb = col;
   1.130 +			if(error >= 0) {
   1.131 +				error -= dx * 2;
   1.132 +				fb += y_inc;
   1.133 +			}
   1.134 +			error += dy * 2;
   1.135 +			fb += x_inc;
   1.136 +		}
   1.137 +	} else {
   1.138 +		error = dx * 2 - dy;
   1.139 +		for(i=0; i<=dy; i++) {
   1.140 +			*fb = col;
   1.141 +			if(error >= 0) {
   1.142 +				error -= dy * 2;
   1.143 +				fb += x_inc;
   1.144 +			}
   1.145 +			error += dx * 2;
   1.146 +			fb += y_inc;
   1.147 +		}
   1.148 +	}
   1.149 +}