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 }
|