crude metaballs
[metatoy] / src / 3dgfx / polyfill.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
5 #include "polyfill.h"
6 #include "gfxutil.h"
7 #include "util.h"
8 #include "colormgr.h"
9
10 /*#define DEBUG_OVERDRAW        G3D_PACK_RGB(10, 10, 10)*/
11
12 /* mode bits:
13  *     bit 0: gouraud
14  *     bit 1: texture
15  *     bit 2: zbuffering
16  */
17 void (*fillfunc[])(struct pvertex*) = {
18         polyfill_flat,
19         polyfill_gouraud,
20         polyfill_tex_flat,
21         polyfill_tex_gouraud,
22         polyfill_flat_zbuf,
23         polyfill_gouraud_zbuf,
24         polyfill_tex_flat_zbuf,
25         polyfill_tex_gouraud_zbuf
26 };
27
28 struct pimage pfill_fb, pfill_tex;
29 uint32_t *pfill_zbuf;
30 struct pgradient pgrad;
31
32 #define EDGEPAD 8
33 static struct pvertex *edgebuf, *left, *right;
34 static int edgebuf_size;
35 static int fbheight;
36
37 /*
38 #define CHECKEDGE(x) \
39         do { \
40                 assert(x >= 0); \
41                 assert(x < fbheight); \
42         } while(0)
43 */
44 #define CHECKEDGE(x)
45
46
47 void polyfill_fbheight(int height)
48 {
49         int newsz = (height * 2 + EDGEPAD * 3) * sizeof *edgebuf;
50
51         if(newsz > edgebuf_size) {
52                 free(edgebuf);
53                 if(!(edgebuf = malloc(newsz))) {
54                         fprintf(stderr, "failed to allocate edge table buffer (%d bytes)\n", newsz);
55                         abort();
56                 }
57                 edgebuf_size = newsz;
58
59                 left = edgebuf + EDGEPAD;
60                 right = edgebuf + height + EDGEPAD * 2;
61
62 #ifndef NDEBUG
63                 memset(edgebuf, 0xaa, EDGEPAD * sizeof *edgebuf);
64                 memset(edgebuf + height + EDGEPAD, 0xaa, EDGEPAD * sizeof *edgebuf);
65                 memset(edgebuf + height * 2 + EDGEPAD * 2, 0xaa, EDGEPAD * sizeof *edgebuf);
66 #endif
67         }
68
69         fbheight = height;
70 }
71
72 void polyfill(int mode, struct pvertex *verts)
73 {
74 #ifndef NDEBUG
75         if(!fillfunc[mode]) {
76                 fprintf(stderr, "polyfill mode %d not implemented\n", mode);
77                 abort();
78         }
79 #endif
80
81         fillfunc[mode](verts);
82 }
83
84 #define VNEXT(p)        (((p) == varr + 2) ? varr : (p) + 1)
85 #define VPREV(p)        ((p) == varr ? varr + 2 : (p) - 1)
86 #define VSUCC(p, side)  ((side) == 0 ? VNEXT(p) : VPREV(p))
87
88 /* extra bits of precision to use when interpolating colors.
89  * try tweaking this if you notice strange quantization artifacts.
90  */
91 #define COLOR_SHIFT     12
92
93
94 #define POLYFILL polyfill_flat
95 #undef GOURAUD
96 #undef TEXMAP
97 #undef ZBUF
98 #include "polytmpl.h"
99 #undef POLYFILL
100
101 #define POLYFILL polyfill_gouraud
102 #define GOURAUD
103 #undef TEXMAP
104 #undef ZBUF
105 #include "polytmpl.h"
106 #undef POLYFILL
107
108 #define POLYFILL polyfill_tex_flat
109 #undef GOURAUD
110 #define TEXMAP
111 #undef ZBUF
112 #include "polytmpl.h"
113 #undef POLYFILL
114
115 #define POLYFILL polyfill_tex_gouraud
116 #define GOURAUD
117 #define TEXMAP
118 #undef ZBUF
119 #include "polytmpl.h"
120 #undef POLYFILL
121
122 /* ---- zbuffer variants ----- */
123
124 #define POLYFILL polyfill_flat_zbuf
125 #undef GOURAUD
126 #undef TEXMAP
127 #define ZBUF
128 #include "polytmpl.h"
129 #undef POLYFILL
130
131 #define POLYFILL polyfill_gouraud_zbuf
132 #define GOURAUD
133 #undef TEXMAP
134 #define ZBUF
135 #include "polytmpl.h"
136 #undef POLYFILL
137
138 #define POLYFILL polyfill_tex_flat_zbuf
139 #undef GOURAUD
140 #define TEXMAP
141 #define ZBUF
142 #include "polytmpl.h"
143 #undef POLYFILL
144
145 #define POLYFILL polyfill_tex_gouraud_zbuf
146 #define GOURAUD
147 #define TEXMAP
148 #define ZBUF
149 #include "polytmpl.h"
150 #undef POLYFILL