- fixed watcom build
[dosdemo] / src / polytmpl.h
1 static uint32_t SCANEDGE(struct pvertex *v0, struct pvertex *v1, struct pvertex *edge)
2 {
3         int i;
4         int32_t x, dx, dy, slope;
5 #ifdef GOURAUD
6         int r, g, b, dr, dg, db;
7         int32_t rslope, gslope, bslope;
8 #endif
9 #ifdef TEXMAP
10         int32_t u, v, du, dv, uslope, vslope;
11 #endif
12         int32_t start_idx, end_idx;
13
14         if(v0->y > v1->y) {
15                 struct pvertex *tmp = v0;
16                 v0 = v1;
17                 v1 = tmp;
18         }
19
20         x = v0->x;
21         dy = v1->y - v0->y;
22         dx = v1->x - v0->x;
23         slope = (dx << 8) / dy;
24 #ifdef GOURAUD
25         r = (v0->r << COLOR_SHIFT);
26         g = (v0->g << COLOR_SHIFT);
27         b = (v0->b << COLOR_SHIFT);
28         dr = (v1->r << COLOR_SHIFT) - r;
29         dg = (v1->g << COLOR_SHIFT) - g;
30         db = (v1->b << COLOR_SHIFT) - b;
31         rslope = (dr << 8) / dy;
32         gslope = (dg << 8) / dy;
33         bslope = (db << 8) / dy;
34 #endif
35 #ifdef TEXMAP
36         u = v0->u;
37         v = v0->v;
38         du = v1->u - v0->u;
39         dv = v1->v - v0->v;
40         uslope = (du << 8) / dy;
41         vslope = (dv << 8) / dy;
42 #endif
43
44         start_idx = v0->y >> 8;
45         end_idx = v1->y >> 8;
46
47         for(i=start_idx; i<end_idx; i++) {
48                 edge[i].x = x;
49                 x += slope;
50 #ifdef GOURAUD
51                 /* we'll store the color in the edge tables with COLOR_SHIFT extra bits of precision */
52                 edge[i].r = r;
53                 edge[i].g = g;
54                 edge[i].b = b;
55                 r += rslope;
56                 g += gslope;
57                 b += bslope;
58 #endif
59 #ifdef TEXMAP
60                 edge[i].u = u;
61                 edge[i].v = v;
62                 u += uslope;
63                 v += vslope;
64 #endif
65         }
66
67         return (uint32_t)start_idx | ((uint32_t)(end_idx - 1) << 16);
68 }
69
70 void POLYFILL(struct pvertex *pv, int nverts)
71 {
72         int i, winding;
73         int topidx = 0, botidx = 0, sltop = pfill_fb.height, slbot = 0;
74         struct pvertex *left, *right;
75         uint16_t color;
76         /* the following variables are used for interpolating horizontally accros scanlines */
77 #if defined(GOURAUD) || defined(TEXMAP)
78         int mid;
79         int32_t dx, tmp;
80 #else
81         /* flat version, just pack the color now */
82         color = PACK_RGB16(pv[0].r, pv[0].g, pv[0].b);
83 #endif
84 #ifdef GOURAUD
85         int32_t r, g, b, dr, dg, db, rslope, gslope, bslope;
86 #endif
87 #ifdef TEXMAP
88         int32_t u, v, du, dv, uslope, vslope;
89 #endif
90
91         for(i=1; i<nverts; i++) {
92                 if(pv[i].y < pv[topidx].y) topidx = i;
93                 if(pv[i].y > pv[botidx].y) botidx = i;
94         }
95
96         winding = 0;
97         for(i=0; i<nverts; i++) {
98                 int next = NEXTIDX(i);
99                 winding += ((pv[next].x - pv[i].x) >> 4) * ((pv[next].y + pv[i].y) >> 4);
100         }
101
102         /* +1 to avoid crashing due to off-by-one rounding errors in the rasterization */
103         left = alloca((pfill_fb.height + 1) * sizeof *left);
104         right = alloca((pfill_fb.height + 1) * sizeof *right);
105
106         for(i=0; i<nverts; i++) {
107                 int next = NEXTIDX(i);
108                 int32_t y0 = pv[i].y;
109                 int32_t y1 = pv[next].y;
110
111                 if((y0 >> 8) == (y1 >> 8)) {
112                         /*if(y0 > y1) {*/
113                                 int i0, i1;
114                                 int idx = y0 >> 8;
115                                 if(pv[i].x < pv[next].x) {
116                                         i0 = i;
117                                         i1 = next;
118                                 } else {
119                                         i0 = next;
120                                         i1 = i;
121                                 }
122                                 left[idx].x = pv[i0].x;
123                                 right[idx].x = pv[i1].x;
124 #ifdef GOURAUD
125                                 left[idx].r = pv[i0].r << COLOR_SHIFT;
126                                 left[idx].g = pv[i0].g << COLOR_SHIFT;
127                                 left[idx].b = pv[i0].b << COLOR_SHIFT;
128                                 right[idx].r = pv[i1].r << COLOR_SHIFT;
129                                 right[idx].g = pv[i1].g << COLOR_SHIFT;
130                                 right[idx].b = pv[i1].b << COLOR_SHIFT;
131 #endif
132 #ifdef TEXMAP
133                                 left[idx].u = pv[i0].u;
134                                 left[idx].v = pv[i0].v;
135                                 right[idx].u = pv[i1].u;
136                                 right[idx].v = pv[i1].v;
137 #endif
138                                 if(idx > slbot) slbot = idx;
139                                 if(idx < sltop) sltop = idx;
140                         /*}*/
141                 } else {
142                         struct pvertex *edge;
143                         uint32_t res, tmp;
144
145                         if(winding < 0) {
146                                 // clockwise
147                                 edge = y0 > y1 ? left : right;
148                         } else {
149                                 // counter-clockwise
150                                 edge = y0 > y1 ? right : left;
151                         }
152                         res = SCANEDGE(pv + i, pv + next, edge);
153                         tmp = (res >> 16) & 0xffff;
154                         if(tmp > slbot) slbot = tmp;
155                         if((tmp = res & 0xffff) < sltop) {
156                                 sltop = tmp;
157                         }
158                 }
159         }
160
161         /* calculate the slopes of all attributes across the largest span out
162          * of the three: middle, top, or bottom.
163          */
164 #ifndef HIGH_QUALITY
165 #if defined(GOURAUD) || defined(TEXMAP)
166         mid = (sltop + slbot) >> 1;
167         dx = right[mid].x - left[mid].x;
168         if((tmp = right[sltop].x - left[sltop].x) > dx) {
169                 dx = tmp;
170                 mid = sltop;
171         }
172         if((tmp = right[slbot].x - left[slbot].x) > dx) {
173                 dx = tmp;
174                 mid = slbot;
175         }
176         if(!dx) dx = 256;       /* avoid division by zero */
177 #endif
178 #ifdef GOURAUD
179         dr = right[mid].r - left[mid].r;
180         dg = right[mid].g - left[mid].g;
181         db = right[mid].b - left[mid].b;
182         rslope = (dr << 8) / dx;
183         gslope = (dg << 8) / dx;
184         bslope = (db << 8) / dx;
185 #endif
186 #ifdef TEXMAP
187         du = right[mid].u - left[mid].u;
188         dv = right[mid].v - left[mid].v;
189         uslope = (du << 8) / dx;
190         vslope = (dv << 8) / dx;
191 #endif
192 #endif  /* !defined(HIGH_QUALITY) */
193
194         /* for each scanline ... */
195         for(i=sltop; i<=slbot; i++) {
196                 uint16_t *pixptr;
197                 int32_t x;
198
199                 x = left[i].x;
200                 pixptr = pfill_fb.pixels + i * pfill_fb.width + (x >> 8);
201
202 #ifdef GOURAUD
203                 r = left[i].r;
204                 g = left[i].g;
205                 b = left[i].b;
206 #endif
207 #ifdef TEXMAP
208                 u = left[i].u;
209                 v = left[i].v;
210 #endif
211
212 #if defined(HIGH_QUALITY) && (defined(GOURAUD) || defined(TEXMAP))
213                 if(!(dx = right[i].x - left[i].x)) dx = 256;
214
215 #ifdef GOURAUD
216                 dr = right[i].r - left[i].r;
217                 dg = right[i].g - left[i].g;
218                 db = right[i].b - left[i].b;
219                 rslope = (dr << 8) / dx;
220                 gslope = (dg << 8) / dx;
221                 bslope = (db << 8) / dx;
222 #endif
223 #ifdef TEXMAP
224                 du = right[i].u - left[i].u;
225                 dv = right[i].v - left[i].v;
226                 uslope = (du << 8) / dx;
227                 vslope = (dv << 8) / dx;
228 #endif
229 #endif  /* HIGH_QUALITY */
230
231                 /* go across the scanline interpolating if necessary */
232                 while(x <= right[i].x) {
233 #if defined(GOURAUD) || defined(TEXMAP)
234                         int cr, cg, cb;
235 #endif
236 #ifdef GOURAUD
237                         /* we upped the color precision to while interpolating the
238                          * edges, now drop the extra bits before packing
239                          */
240                         cr = r < 0 ? 0 : (r >> COLOR_SHIFT);
241                         cg = g < 0 ? 0 : (g >> COLOR_SHIFT);
242                         cb = b < 0 ? 0 : (b >> COLOR_SHIFT);
243                         if(cr > 255) cr = 255;
244                         if(cg > 255) cg = 255;
245                         if(cb > 255) cb = 255;
246                         r += rslope;
247                         g += gslope;
248                         b += bslope;
249 #endif
250 #ifdef TEXMAP
251                         {
252                                 int tx = (u >> (16 - pfill_tex.xshift)) & pfill_tex.xmask;
253                                 int ty = (v >> (16 - pfill_tex.yshift)) & pfill_tex.ymask;
254                                 uint16_t texel = pfill_tex.pixels[(ty << pfill_tex.xshift) + tx];
255 #ifdef GOURAUD
256                                 /* This is not correct, should be /255, but it's much faster
257                                  * to shift by 8 (/256), and won't make a huge difference
258                                  */
259                                 cr = (cr * UNPACK_R16(texel)) >> 8;
260                                 cg = (cg * UNPACK_G16(texel)) >> 8;
261                                 cb = (cb * UNPACK_B16(texel)) >> 8;
262 #else
263                                 cr = UNPACK_R16(texel);
264                                 cg = UNPACK_G16(texel);
265                                 cb = UNPACK_B16(texel);
266 #endif
267                         }
268                         u += uslope;
269                         v += vslope;
270 #endif
271 #if defined(GOURAUD) || defined(TEXMAP)
272                         color = PACK_RGB16(cr, cg, cb);
273 #endif
274
275 #ifdef DEBUG_OVERDRAW
276                         *pixptr++ += DEBUG_OVERDRAW;
277 #else
278                         *pixptr++ = color;
279 #endif
280                         x += 256;
281                 }
282         }
283 }
284