foo
[dos_low3d] / src / polyfill.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "3dgfx.h"
4 #include "util.h"
5
6 static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2);
7 static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2);
8
9 void g3d_polyfill(struct g3d_vertex *verts)
10 {
11         int i, topidx, botidx, mididx;
12         int32_t dx, dy, dym;
13         struct g3d_vertex vtmp;
14
15         topidx = botidx = 0;
16         for(i=1; i<3; i++) {
17                 if(verts[i].y < verts[topidx].y) {
18                         topidx = i;
19                 }
20                 if(verts[i].y > verts[botidx].y) {
21                         botidx = i;
22                 }
23         }
24         mididx = (topidx + 1) % 3;
25         if(mididx == botidx) mididx = (mididx + 1) % 3;
26
27         dy = verts[botidx].y - verts[topidx].y;
28         if(dy == 0) return;
29
30         dx = verts[botidx].x - verts[topidx].x;
31         dym = verts[mididx].y - verts[topidx].y;
32         vtmp.x = muldiv(dx, dym, dy) + verts[topidx].x; /* dx * dym / dy + vtop.x */
33         vtmp.y = verts[mididx].y;
34
35         if(verts[topidx].y != verts[mididx].y) {
36                 filltop(verts + topidx, verts + mididx, &vtmp);
37         }
38         if(verts[mididx].y != verts[botidx].y) {
39                 fillbot(verts + mididx, &vtmp, verts + botidx);
40         }
41 }
42
43 static void filltop(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)
44 {
45         struct g3d_vertex *vtmp;
46         int x, xn, y, endy, len;
47         int32_t xl, xr, dxl, dxr, dxldy, dxrdy, dy;
48         unsigned char *fbptr;
49
50         if(v1->x > v2->x) {
51                 vtmp = v1;
52                 v1 = v2;
53                 v2 = vtmp;
54         }
55
56         y = v0->y >> 8;
57         endy = v1->y >> 8;
58         if(endy > YRES) endy = YRES;
59         x = v0->x >> 8;
60
61         fbptr = g3d_fbpixels + y * XRES + x;
62
63         xl = xr = v0->x;
64         dy = v1->y - v0->y;
65         dxl = v1->x - v0->x;
66         dxr = v2->x - v0->x;
67         dxldy = (dxl << 8) / dy;
68         dxrdy = (dxr << 8) / dy;
69
70         while(y++ < endy) {
71                 if(y > 0) {
72                         len = (xr - xl) >> 8;
73                         if(len > 0) memset(fbptr, g3d_curcidx, len);
74                 }
75
76                 xl += dxldy;
77                 xr += dxrdy;
78                 xn = xl >> 8;
79                 fbptr += XRES + (xn - x);
80                 x = xn;
81         }
82 }
83
84 static void fillbot(struct g3d_vertex *v0, struct g3d_vertex *v1, struct g3d_vertex *v2)
85 {
86         struct g3d_vertex *vtmp;
87         int x, xn, y, endy, len;
88         int32_t xl, xr, dxl, dxr, dxldy, dxrdy, dy;
89         unsigned char *fbptr;
90
91         if(v0->x > v1->x) {
92                 vtmp = v0;
93                 v0 = v1;
94                 v1 = vtmp;
95         }
96
97         y = v0->y >> 8;
98         endy = v2->y >> 8;
99         if(endy > YRES) endy = YRES;
100         x = v0->x >> 8;
101
102         fbptr = g3d_fbpixels + y * XRES + x;
103
104         xl = v0->x;
105         xr = v1->x;
106         dy = v2->y - v0->y;
107         dxl = v2->x - v0->x;
108         dxr = v2->x - v1->x;
109         dxldy = (dxl << 8) / dy;
110         dxrdy = (dxr << 8) / dy;
111
112         while(y++ < endy) {
113                 if(y > 0) {
114                         len = (xr - xl) >> 8;
115                         if(len > 0) memset(fbptr, g3d_curcidx, len);
116                 }
117
118                 xl += dxldy;
119                 xr += dxrdy;
120                 xn = xl >> 8;
121                 fbptr += XRES + (xn - x);
122                 x = xn;
123         }
124 }