rev |
line source |
nuclear@5
|
1 #include "config.h"
|
nuclear@5
|
2 #include <string.h>
|
nuclear@6
|
3 #include <assert.h>
|
nuclear@5
|
4 #include "polyfill.h"
|
nuclear@5
|
5 #include "fixed.h"
|
nuclear@5
|
6 #include "gbasys.h"
|
nuclear@5
|
7
|
nuclear@5
|
8 static void fill_scanline(int y, int x0, int x1, uint16_t color);
|
nuclear@5
|
9
|
nuclear@5
|
10 void draw_poly(int num, const pvec3 *verts, uint16_t color)
|
nuclear@5
|
11 {
|
nuclear@5
|
12 int i, topidx = 0, botidx = 0;
|
nuclear@5
|
13 int lidx[2], ridx[2];
|
nuclear@5
|
14 int32_t y, topy, boty;
|
nuclear@5
|
15 int32_t ldy, rdy, ldxdy, rdxdy;
|
nuclear@5
|
16 int32_t lx, rx;
|
nuclear@5
|
17 int start, end;
|
nuclear@5
|
18
|
nuclear@5
|
19 topy = boty = verts[0].y;
|
nuclear@5
|
20 for(i=1; i<num; i++) {
|
nuclear@5
|
21 int32_t y = verts[i].y;
|
nuclear@5
|
22 if(y < topy) {
|
nuclear@5
|
23 topy = y;
|
nuclear@5
|
24 topidx = i;
|
nuclear@5
|
25 }
|
nuclear@5
|
26 if(y > boty) {
|
nuclear@5
|
27 boty = y;
|
nuclear@5
|
28 botidx = i;
|
nuclear@5
|
29 }
|
nuclear@5
|
30 }
|
nuclear@5
|
31
|
nuclear@5
|
32 lidx[0] = ridx[0] = topidx;
|
nuclear@5
|
33 lidx[1] = topidx ? topidx - 1 : num - 1;
|
nuclear@5
|
34 ridx[1] = (topidx + 1) % num;
|
nuclear@5
|
35
|
nuclear@6
|
36 if(verts[ridx[1]].x < verts[lidx[1]].x) {
|
nuclear@5
|
37 return; /* backface (CCW) */
|
nuclear@5
|
38 }
|
nuclear@5
|
39
|
nuclear@5
|
40 lx = rx = verts[lidx[0]].x;
|
nuclear@5
|
41
|
nuclear@6
|
42 /* TODO handle ldy == 0 or rdy == 0 */
|
nuclear@5
|
43 ldy = verts[lidx[1]].y - verts[lidx[0]].y;
|
nuclear@5
|
44 ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
|
nuclear@5
|
45
|
nuclear@6
|
46 rdy = verts[ridx[1]].y - verts[ridx[0]].y;
|
nuclear@5
|
47 rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
|
nuclear@5
|
48
|
nuclear@5
|
49 start = topy >> 16;
|
nuclear@5
|
50 end = boty >> 16;
|
nuclear@5
|
51
|
nuclear@6
|
52 if(end >= HEIGHT) end = HEIGHT - 1;
|
nuclear@6
|
53
|
nuclear@5
|
54 y = topy;
|
nuclear@5
|
55 for(i=start; i<end; i++) {
|
nuclear@5
|
56 unsigned short x0, x1;
|
nuclear@5
|
57
|
nuclear@5
|
58 x0 = lx < 0 ? 0 : (lx >> 16);
|
nuclear@6
|
59 x1 = (rx >> 16) >= WIDTH ? WIDTH - 1 : (rx >> 16);
|
nuclear@5
|
60
|
nuclear@6
|
61 if(i >= 0 && x1 > x0) {
|
nuclear@6
|
62 fill_scanline(i, x0, x1, color);
|
nuclear@6
|
63 }
|
nuclear@5
|
64
|
nuclear@5
|
65 if(y >= verts[lidx[1]].y) {
|
nuclear@5
|
66 lidx[0] = lidx[1];
|
nuclear@5
|
67 lidx[1] = lidx[1] ? lidx[1] - 1 : num - 1;
|
nuclear@5
|
68 ldy = verts[lidx[1]].y - verts[lidx[0]].y;
|
nuclear@5
|
69 if(ldy < 0) {
|
nuclear@5
|
70 break;
|
nuclear@5
|
71 }
|
nuclear@5
|
72 ldxdy = x16div(verts[lidx[1]].x - lx, ldy);
|
nuclear@5
|
73 }
|
nuclear@5
|
74 if(y >= verts[ridx[1]].y) {
|
nuclear@5
|
75 ridx[0] = ridx[1];
|
nuclear@5
|
76 ridx[1] = (ridx[1] + 1) % num;
|
nuclear@5
|
77 rdy = verts[ridx[1]].y - verts[ridx[0]].y;
|
nuclear@5
|
78 if(rdy < 0) {
|
nuclear@5
|
79 break;
|
nuclear@5
|
80 }
|
nuclear@5
|
81 rdxdy = x16div(verts[ridx[1]].x - rx, rdy);
|
nuclear@5
|
82 }
|
nuclear@5
|
83
|
nuclear@5
|
84 lx += ldxdy;
|
nuclear@5
|
85 rx += rdxdy;
|
nuclear@6
|
86 y += 65536;
|
nuclear@5
|
87 }
|
nuclear@5
|
88 }
|
nuclear@5
|
89
|
nuclear@5
|
90 static void fill_scanline(int y, int x0, int x1, uint16_t color)
|
nuclear@5
|
91 {
|
nuclear@5
|
92 int i;
|
nuclear@5
|
93 uint16_t *pixels = (uint16_t*)back_buffer->pixels + y * WIDTH + x0;
|
nuclear@5
|
94
|
nuclear@5
|
95 for(i=x0; i<x1; i++) {
|
nuclear@5
|
96 *pixels++ = color;
|
nuclear@5
|
97 }
|
nuclear@5
|
98 }
|
nuclear@8
|
99
|
nuclear@8
|
100
|
nuclear@8
|
101 void draw_point(const pvec3 *v, uint16_t color)
|
nuclear@8
|
102 {
|
nuclear@8
|
103 int x = v->x >> 16;
|
nuclear@8
|
104 int y = v->y >> 16;
|
nuclear@8
|
105 uint16_t *pixels = (uint16_t*)back_buffer->pixels;
|
nuclear@8
|
106
|
nuclear@8
|
107 if(x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) {
|
nuclear@8
|
108 return;
|
nuclear@8
|
109 }
|
nuclear@8
|
110
|
nuclear@8
|
111 pixels[y * WIDTH + x] = color;
|
nuclear@8
|
112 }
|