rayzor

view 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 source
1 #include "lines.h"
3 enum {
4 IN = 0,
5 LEFT = 1,
6 RIGHT = 2,
7 TOP = 4,
8 BOTTOM = 8
9 };
11 static int outcode(int x, int y, int minx, int miny, int maxx, int maxy)
12 {
13 int code = 0;
15 if(x < minx) {
16 code |= LEFT;
17 } else if(x > maxx) {
18 code |= RIGHT;
19 }
20 if(y < miny) {
21 code |= TOP;
22 } else if(y > maxy) {
23 code |= BOTTOM;
24 }
25 return code;
26 }
28 #define FIXMUL(a, b) (((a) * (b)) >> 8)
29 #define FIXDIV(a, b) (((a) << 8) / (b))
31 #define LERP(a, b, t) ((a) + FIXMUL((b) - (a), (t)))
33 int clip_line2d(int *x0, int *y0, int *x1, int *y1, const int *vp)
34 {
35 int oc_out;
36 int minx = vp[0];
37 int miny = vp[1];
38 int maxx = vp[0] + vp[2] - 1;
39 int maxy = vp[1] + vp[3] - 1;
41 int oc0 = outcode(*x0, *y0, minx, miny, maxx, maxy);
42 int oc1 = outcode(*x1, *y1, minx, miny, maxx, maxy);
44 int32_t fx0, fy0, fx1, fy1, fminx, fminy, fmaxx, fmaxy;
46 if(!(oc0 | oc1)) return 1; /* both points are inside */
48 fx0 = *x0 << 8;
49 fy0 = *y0 << 8;
50 fx1 = *x1 << 8;
51 fy1 = *y1 << 8;
52 fminx = minx << 8;
53 fminy = miny << 8;
54 fmaxx = maxx << 8;
55 fmaxy = maxy << 8;
57 for(;;) {
58 int32_t x, y, t;
60 if(oc0 & oc1) return 0; /* both have points with the same outbit, not visible */
61 if(!(oc0 | oc1)) break; /* both points are inside */
63 oc_out = oc0 ? oc0 : oc1;
65 if(oc_out & TOP) {
66 t = FIXDIV(fminy - fy0, fy1 - fy0);
67 x = LERP(fx0, fx1, t);
68 y = fminy;
69 } else if(oc_out & BOTTOM) {
70 t = FIXDIV(fmaxy - fy0, fy1 - fy0);
71 x = LERP(fx0, fx1, t);
72 y = fmaxy;
73 } else if(oc_out & LEFT) {
74 t = FIXDIV(fminx - fx0, fx1 - fx0);
75 x = fminx;
76 y = LERP(fy0, fy1, t);
77 } else if(oc_out & RIGHT) {
78 t = FIXDIV(fmaxx - fx0, fx1 - fx0);
79 x = fmaxx;
80 y = LERP(fy0, fy1, t);
81 }
83 if(oc_out == oc0) {
84 fx0 = x;
85 fy0 = y;
86 oc0 = outcode(fx0 >> 8, fy0 >> 8, minx, miny, maxx, maxy);
87 } else {
88 fx1 = x;
89 fy1 = y;
90 oc1 = outcode(fx1 >> 8, fy1 >> 8, minx, miny, maxx, maxy);
91 }
92 }
94 *x0 = fx0 >> 8;
95 *y0 = fy0 >> 8;
96 *x1 = fx1 >> 8;
97 *y1 = fy1 >> 8;
98 return 1;
99 }
101 void draw_line(uint32_t *fb, int fbwidth, uint32_t col, int x0, int y0, int x1, int y1)
102 {
103 int i, dx, dy, x_inc, y_inc, error;
105 fb += y0 * fbwidth + x0;
107 dx = x1 - x0;
108 dy = y1 - y0;
110 if(dx >= 0) {
111 x_inc = 1;
112 } else {
113 x_inc = -1;
114 dx = -dx;
115 }
116 if(dy >= 0) {
117 y_inc = fbwidth;
118 } else {
119 y_inc = -fbwidth;
120 dy = -dy;
121 }
123 if(dx > dy) {
124 error = dy * 2 - dx;
125 for(i=0; i<=dx; i++) {
126 *fb = col;
127 if(error >= 0) {
128 error -= dx * 2;
129 fb += y_inc;
130 }
131 error += dy * 2;
132 fb += x_inc;
133 }
134 } else {
135 error = dx * 2 - dy;
136 for(i=0; i<=dy; i++) {
137 *fb = col;
138 if(error >= 0) {
139 error -= dy * 2;
140 fb += x_inc;
141 }
142 error += dx * 2;
143 fb += y_inc;
144 }
145 }
146 }