1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 // d_polyset.c: routines for drawing sets of polygons sharing the same
21 // texture (used for Alias models)
22 
23 #include "quakedef.h"
24 #include "r_local.h"
25 #include "d_local.h"
26 
27 // TODO: put in span spilling to shrink list size
28 // !!! if this is changed, it must be changed in d_polysa.s too !!!
29 #define DPS_MAXSPANS			MAXHEIGHT+1
30 									// 1 extra for spanpackage that marks end
31 
32 // !!! if this is changed, it must be changed in asm_draw.h too !!!
33 typedef struct {
34 	void			*pdest;
35 	short			*pz;
36 	int				count;
37 	byte			*ptex;
38 	int				sfrac, tfrac, light, zi;
39 } spanpackage_t;
40 
41 typedef struct {
42 	int		isflattop;
43 	int		numleftedges;
44 	int		*pleftedgevert0;
45 	int		*pleftedgevert1;
46 	int		*pleftedgevert2;
47 	int		numrightedges;
48 	int		*prightedgevert0;
49 	int		*prightedgevert1;
50 	int		*prightedgevert2;
51 } edgetable;
52 
53 int	r_p0[6], r_p1[6], r_p2[6];
54 
55 byte		*d_pcolormap;
56 
57 int			d_aflatcolor;
58 int			d_xdenom;
59 
60 edgetable	*pedgetable;
61 
62 edgetable	edgetables[12] = {
63 	{0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2 },
64 	{0, 2, r_p1, r_p0, r_p2,   1, r_p1, r_p2, NULL},
65 	{1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
66 	{0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0 },
67 	{0, 2, r_p0, r_p2, r_p1,   1, r_p0, r_p1, NULL},
68 	{0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
69 	{0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1 },
70 	{0, 2, r_p2, r_p1, r_p0,   1, r_p2, r_p0, NULL},
71 	{0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
72 	{1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
73 	{1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
74 	{0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
75 };
76 
77 // FIXME: some of these can become statics
78 int				a_sstepxfrac, a_tstepxfrac, r_lstepx, a_ststepxwhole;
79 int				r_sstepx, r_tstepx, r_lstepy, r_sstepy, r_tstepy;
80 int				r_zistepx, r_zistepy;
81 int				d_aspancount, d_countextrastep;
82 
83 spanpackage_t			*a_spans;
84 spanpackage_t			*d_pedgespanpackage;
85 static int				ystart;
86 byte					*d_pdest, *d_ptex;
87 short					*d_pz;
88 int						d_sfrac, d_tfrac, d_light, d_zi;
89 int						d_ptexextrastep, d_sfracextrastep;
90 int						d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
91 int						d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
92 int						d_sfracbasestep, d_tfracbasestep;
93 int						d_ziextrastep, d_zibasestep;
94 int						d_pzextrastep, d_pzbasestep;
95 
96 typedef struct {
97 	int		quotient;
98 	int		remainder;
99 } adivtab_t;
100 
101 static adivtab_t	adivtab[32*32] = {
102 #include "adivtab.h"
103 };
104 
105 byte	*skintable[MAX_LBM_HEIGHT];
106 int		skinwidth;
107 byte	*skinstart;
108 
109 void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage);
110 void D_PolysetCalcGradients (int skinwidth);
111 void D_DrawSubdiv (void);
112 void D_DrawNonSubdiv (void);
113 void D_PolysetRecursiveTriangle (int *p1, int *p2, int *p3);
114 void D_PolysetSetEdgeTable (void);
115 void D_RasterizeAliasPolySmooth (void);
116 void D_PolysetScanLeftEdge (int height);
117 
118 #if	!id386
119 
120 /*
121 ================
122 D_PolysetDraw
123 ================
124 */
D_PolysetDraw(void)125 void D_PolysetDraw (void)
126 {
127 	spanpackage_t	spans[DPS_MAXSPANS + 1 +
128 			((CACHE_SIZE - 1) / sizeof(spanpackage_t)) + 1];
129 						// one extra because of cache line pretouching
130 
131 	a_spans = (spanpackage_t *)
132 			(((long)&spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
133 
134 	if (r_affinetridesc.drawtype)
135 	{
136 		D_DrawSubdiv ();
137 	}
138 	else
139 	{
140 		D_DrawNonSubdiv ();
141 	}
142 }
143 
144 
145 /*
146 ================
147 D_PolysetDrawFinalVerts
148 ================
149 */
D_PolysetDrawFinalVerts(finalvert_t * fv,int numverts)150 void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts)
151 {
152 	int		i, z;
153 	short	*zbuf;
154 
155 	for (i=0 ; i<numverts ; i++, fv++)
156 	{
157 	// valid triangle coordinates for filling can include the bottom and
158 	// right clip edges, due to the fill rule; these shouldn't be drawn
159 		if ((fv->v[0] < r_refdef.vrectright) &&
160 			(fv->v[1] < r_refdef.vrectbottom))
161 		{
162 			z = fv->v[5]>>16;
163 			zbuf = zspantable[fv->v[1]] + fv->v[0];
164 			if (z >= *zbuf)
165 			{
166 				int		pix;
167 
168 				*zbuf = z;
169 				pix = skintable[fv->v[3]>>16][fv->v[2]>>16];
170 				pix = ((byte *)acolormap)[pix + (fv->v[4] & 0xFF00) ];
171 				d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
172 			}
173 		}
174 	}
175 }
176 
177 
178 /*
179 ================
180 D_DrawSubdiv
181 ================
182 */
D_DrawSubdiv(void)183 void D_DrawSubdiv (void)
184 {
185 	mtriangle_t		*ptri;
186 	finalvert_t		*pfv, *index0, *index1, *index2;
187 	int				i;
188 	int				lnumtriangles;
189 
190 	pfv = r_affinetridesc.pfinalverts;
191 	ptri = r_affinetridesc.ptriangles;
192 	lnumtriangles = r_affinetridesc.numtriangles;
193 
194 	for (i=0 ; i<lnumtriangles ; i++)
195 	{
196 		index0 = pfv + ptri[i].vertindex[0];
197 		index1 = pfv + ptri[i].vertindex[1];
198 		index2 = pfv + ptri[i].vertindex[2];
199 
200 		if (((index0->v[1]-index1->v[1]) *
201 			 (index0->v[0]-index2->v[0]) -
202 			 (index0->v[0]-index1->v[0]) *
203 			 (index0->v[1]-index2->v[1])) >= 0)
204 		{
205 			continue;
206 		}
207 
208 		d_pcolormap = &((byte *)acolormap)[index0->v[4] & 0xFF00];
209 
210 		if (ptri[i].facesfront)
211 		{
212 			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
213 		}
214 		else
215 		{
216 			int		s0, s1, s2;
217 
218 			s0 = index0->v[2];
219 			s1 = index1->v[2];
220 			s2 = index2->v[2];
221 
222 			if (index0->flags & ALIAS_ONSEAM)
223 				index0->v[2] += r_affinetridesc.seamfixupX16;
224 			if (index1->flags & ALIAS_ONSEAM)
225 				index1->v[2] += r_affinetridesc.seamfixupX16;
226 			if (index2->flags & ALIAS_ONSEAM)
227 				index2->v[2] += r_affinetridesc.seamfixupX16;
228 
229 			D_PolysetRecursiveTriangle(index0->v, index1->v, index2->v);
230 
231 			index0->v[2] = s0;
232 			index1->v[2] = s1;
233 			index2->v[2] = s2;
234 		}
235 	}
236 }
237 
238 
239 /*
240 ================
241 D_DrawNonSubdiv
242 ================
243 */
D_DrawNonSubdiv(void)244 void D_DrawNonSubdiv (void)
245 {
246 	mtriangle_t		*ptri;
247 	finalvert_t		*pfv, *index0, *index1, *index2;
248 	int				i;
249 	int				lnumtriangles;
250 
251 	pfv = r_affinetridesc.pfinalverts;
252 	ptri = r_affinetridesc.ptriangles;
253 	lnumtriangles = r_affinetridesc.numtriangles;
254 
255 	for (i=0 ; i<lnumtriangles ; i++, ptri++)
256 	{
257 		index0 = pfv + ptri->vertindex[0];
258 		index1 = pfv + ptri->vertindex[1];
259 		index2 = pfv + ptri->vertindex[2];
260 
261 		d_xdenom = (index0->v[1]-index1->v[1]) *
262 				(index0->v[0]-index2->v[0]) -
263 				(index0->v[0]-index1->v[0])*(index0->v[1]-index2->v[1]);
264 
265 		if (d_xdenom >= 0)
266 		{
267 			continue;
268 		}
269 
270 		r_p0[0] = index0->v[0];		// u
271 		r_p0[1] = index0->v[1];		// v
272 		r_p0[2] = index0->v[2];		// s
273 		r_p0[3] = index0->v[3];		// t
274 		r_p0[4] = index0->v[4];		// light
275 		r_p0[5] = index0->v[5];		// iz
276 
277 		r_p1[0] = index1->v[0];
278 		r_p1[1] = index1->v[1];
279 		r_p1[2] = index1->v[2];
280 		r_p1[3] = index1->v[3];
281 		r_p1[4] = index1->v[4];
282 		r_p1[5] = index1->v[5];
283 
284 		r_p2[0] = index2->v[0];
285 		r_p2[1] = index2->v[1];
286 		r_p2[2] = index2->v[2];
287 		r_p2[3] = index2->v[3];
288 		r_p2[4] = index2->v[4];
289 		r_p2[5] = index2->v[5];
290 
291 		if (!ptri->facesfront)
292 		{
293 			if (index0->flags & ALIAS_ONSEAM)
294 				r_p0[2] += r_affinetridesc.seamfixupX16;
295 			if (index1->flags & ALIAS_ONSEAM)
296 				r_p1[2] += r_affinetridesc.seamfixupX16;
297 			if (index2->flags & ALIAS_ONSEAM)
298 				r_p2[2] += r_affinetridesc.seamfixupX16;
299 		}
300 
301 		D_PolysetSetEdgeTable ();
302 		D_RasterizeAliasPolySmooth ();
303 	}
304 }
305 
306 
307 /*
308 ================
309 D_PolysetRecursiveTriangle
310 ================
311 */
D_PolysetRecursiveTriangle(int * lp1,int * lp2,int * lp3)312 void D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3)
313 {
314 	int		*temp;
315 	int		d;
316 	int		new[6];
317 	int		z;
318 	short	*zbuf;
319 
320 	d = lp2[0] - lp1[0];
321 	if (d < -1 || d > 1)
322 		goto split;
323 	d = lp2[1] - lp1[1];
324 	if (d < -1 || d > 1)
325 		goto split;
326 
327 	d = lp3[0] - lp2[0];
328 	if (d < -1 || d > 1)
329 		goto split2;
330 	d = lp3[1] - lp2[1];
331 	if (d < -1 || d > 1)
332 		goto split2;
333 
334 	d = lp1[0] - lp3[0];
335 	if (d < -1 || d > 1)
336 		goto split3;
337 	d = lp1[1] - lp3[1];
338 	if (d < -1 || d > 1)
339 	{
340 split3:
341 		temp = lp1;
342 		lp1 = lp3;
343 		lp3 = lp2;
344 		lp2 = temp;
345 
346 		goto split;
347 	}
348 
349 	return;			// entire tri is filled
350 
351 split2:
352 	temp = lp1;
353 	lp1 = lp2;
354 	lp2 = lp3;
355 	lp3 = temp;
356 
357 split:
358 // split this edge
359 	new[0] = (lp1[0] + lp2[0]) >> 1;
360 	new[1] = (lp1[1] + lp2[1]) >> 1;
361 	new[2] = (lp1[2] + lp2[2]) >> 1;
362 	new[3] = (lp1[3] + lp2[3]) >> 1;
363 	new[5] = (lp1[5] + lp2[5]) >> 1;
364 
365 // draw the point if splitting a leading edge
366 	if (lp2[1] > lp1[1])
367 		goto nodraw;
368 	if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
369 		goto nodraw;
370 
371 
372 	z = new[5]>>16;
373 	zbuf = zspantable[new[1]] + new[0];
374 	if (z >= *zbuf)
375 	{
376 		int		pix;
377 
378 		*zbuf = z;
379 		pix = d_pcolormap[skintable[new[3]>>16][new[2]>>16]];
380 		d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
381 	}
382 
383 nodraw:
384 // recursively continue
385 	D_PolysetRecursiveTriangle (lp3, lp1, new);
386 	D_PolysetRecursiveTriangle (lp3, new, lp2);
387 }
388 
389 #endif	// !id386
390 
391 
392 /*
393 ================
394 D_PolysetUpdateTables
395 ================
396 */
D_PolysetUpdateTables(void)397 void D_PolysetUpdateTables (void)
398 {
399 	int		i;
400 	byte	*s;
401 
402 	if (r_affinetridesc.skinwidth != skinwidth ||
403 		r_affinetridesc.pskin != skinstart)
404 	{
405 		skinwidth = r_affinetridesc.skinwidth;
406 		skinstart = r_affinetridesc.pskin;
407 		s = skinstart;
408 		for (i=0 ; i<MAX_LBM_HEIGHT ; i++, s+=skinwidth)
409 			skintable[i] = s;
410 	}
411 }
412 
413 
414 #if	!id386
415 
416 /*
417 ===================
418 D_PolysetScanLeftEdge
419 ====================
420 */
D_PolysetScanLeftEdge(int height)421 void D_PolysetScanLeftEdge (int height)
422 {
423 
424 	do
425 	{
426 		d_pedgespanpackage->pdest = d_pdest;
427 		d_pedgespanpackage->pz = d_pz;
428 		d_pedgespanpackage->count = d_aspancount;
429 		d_pedgespanpackage->ptex = d_ptex;
430 
431 		d_pedgespanpackage->sfrac = d_sfrac;
432 		d_pedgespanpackage->tfrac = d_tfrac;
433 
434 	// FIXME: need to clamp l, s, t, at both ends?
435 		d_pedgespanpackage->light = d_light;
436 		d_pedgespanpackage->zi = d_zi;
437 
438 		d_pedgespanpackage++;
439 
440 		errorterm += erroradjustup;
441 		if (errorterm >= 0)
442 		{
443 			d_pdest += d_pdestextrastep;
444 			d_pz += d_pzextrastep;
445 			d_aspancount += d_countextrastep;
446 			d_ptex += d_ptexextrastep;
447 			d_sfrac += d_sfracextrastep;
448 			d_ptex += d_sfrac >> 16;
449 
450 			d_sfrac &= 0xFFFF;
451 			d_tfrac += d_tfracextrastep;
452 			if (d_tfrac & 0x10000)
453 			{
454 				d_ptex += r_affinetridesc.skinwidth;
455 				d_tfrac &= 0xFFFF;
456 			}
457 			d_light += d_lightextrastep;
458 			d_zi += d_ziextrastep;
459 			errorterm -= erroradjustdown;
460 		}
461 		else
462 		{
463 			d_pdest += d_pdestbasestep;
464 			d_pz += d_pzbasestep;
465 			d_aspancount += ubasestep;
466 			d_ptex += d_ptexbasestep;
467 			d_sfrac += d_sfracbasestep;
468 			d_ptex += d_sfrac >> 16;
469 			d_sfrac &= 0xFFFF;
470 			d_tfrac += d_tfracbasestep;
471 			if (d_tfrac & 0x10000)
472 			{
473 				d_ptex += r_affinetridesc.skinwidth;
474 				d_tfrac &= 0xFFFF;
475 			}
476 			d_light += d_lightbasestep;
477 			d_zi += d_zibasestep;
478 		}
479 	} while (--height);
480 }
481 
482 #endif	// !id386
483 
484 
485 /*
486 ===================
487 D_PolysetSetUpForLineScan
488 ====================
489 */
D_PolysetSetUpForLineScan(fixed8_t startvertu,fixed8_t startvertv,fixed8_t endvertu,fixed8_t endvertv)490 void D_PolysetSetUpForLineScan(fixed8_t startvertu, fixed8_t startvertv,
491 		fixed8_t endvertu, fixed8_t endvertv)
492 {
493 	double		dm, dn;
494 	int			tm, tn;
495 	adivtab_t	*ptemp;
496 
497 // TODO: implement x86 version
498 
499 	errorterm = -1;
500 
501 	tm = endvertu - startvertu;
502 	tn = endvertv - startvertv;
503 
504 	if (((tm <= 16) && (tm >= -15)) &&
505 		((tn <= 16) && (tn >= -15)))
506 	{
507 		ptemp = &adivtab[((tm+15) << 5) + (tn+15)];
508 		ubasestep = ptemp->quotient;
509 		erroradjustup = ptemp->remainder;
510 		erroradjustdown = tn;
511 	}
512 	else
513 	{
514 		dm = (double)tm;
515 		dn = (double)tn;
516 
517 		FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
518 
519 		erroradjustdown = dn;
520 	}
521 }
522 
523 
524 #if	!id386
525 
526 /*
527 ================
528 D_PolysetCalcGradients
529 ================
530 */
D_PolysetCalcGradients(int skinwidth)531 void D_PolysetCalcGradients (int skinwidth)
532 {
533 	float	xstepdenominv, ystepdenominv, t0, t1;
534 	float	p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
535 
536 	p00_minus_p20 = r_p0[0] - r_p2[0];
537 	p01_minus_p21 = r_p0[1] - r_p2[1];
538 	p10_minus_p20 = r_p1[0] - r_p2[0];
539 	p11_minus_p21 = r_p1[1] - r_p2[1];
540 
541 	xstepdenominv = 1.0 / (float)d_xdenom;
542 
543 	ystepdenominv = -xstepdenominv;
544 
545 // ceil () for light so positive steps are exaggerated, negative steps
546 // diminished,  pushing us away from underflow toward overflow. Underflow is
547 // very visible, overflow is very unlikely, because of ambient lighting
548 	t0 = r_p0[4] - r_p2[4];
549 	t1 = r_p1[4] - r_p2[4];
550 	r_lstepx = (int)
551 			ceil((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
552 	r_lstepy = (int)
553 			ceil((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
554 
555 	t0 = r_p0[2] - r_p2[2];
556 	t1 = r_p1[2] - r_p2[2];
557 	r_sstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
558 			xstepdenominv);
559 	r_sstepy = (int)((t1 * p00_minus_p20 - t0* p10_minus_p20) *
560 			ystepdenominv);
561 
562 	t0 = r_p0[3] - r_p2[3];
563 	t1 = r_p1[3] - r_p2[3];
564 	r_tstepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
565 			xstepdenominv);
566 	r_tstepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
567 			ystepdenominv);
568 
569 	t0 = r_p0[5] - r_p2[5];
570 	t1 = r_p1[5] - r_p2[5];
571 	r_zistepx = (int)((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
572 			xstepdenominv);
573 	r_zistepy = (int)((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
574 			ystepdenominv);
575 
576 #if	id386
577 	a_sstepxfrac = r_sstepx << 16;
578 	a_tstepxfrac = r_tstepx << 16;
579 #else
580 	a_sstepxfrac = r_sstepx & 0xFFFF;
581 	a_tstepxfrac = r_tstepx & 0xFFFF;
582 #endif
583 
584 	a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
585 }
586 
587 #endif	// !id386
588 
589 
590 #if 0
591 byte gelmap[256];
592 void InitGel (byte *palette)
593 {
594 	int		i;
595 	int		r;
596 
597 	for (i=0 ; i<256 ; i++)
598 	{
599 //		r = (palette[i*3]>>4);
600 		r = (palette[i*3] + palette[i*3+1] + palette[i*3+2])/(16*3);
601 		gelmap[i] = /* 64 */ 0 + r;
602 	}
603 }
604 #endif
605 
606 
607 #if	!id386
608 
609 /*
610 ================
611 D_PolysetDrawSpans8
612 ================
613 */
D_PolysetDrawSpans8(spanpackage_t * pspanpackage)614 void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage)
615 {
616 	int		lcount;
617 	byte	*lpdest;
618 	byte	*lptex;
619 	int		lsfrac, ltfrac;
620 	int		llight;
621 	int		lzi;
622 	short	*lpz;
623 
624 	do
625 	{
626 		lcount = d_aspancount - pspanpackage->count;
627 
628 		errorterm += erroradjustup;
629 		if (errorterm >= 0)
630 		{
631 			d_aspancount += d_countextrastep;
632 			errorterm -= erroradjustdown;
633 		}
634 		else
635 		{
636 			d_aspancount += ubasestep;
637 		}
638 
639 		if (lcount)
640 		{
641 			lpdest = pspanpackage->pdest;
642 			lptex = pspanpackage->ptex;
643 			lpz = pspanpackage->pz;
644 			lsfrac = pspanpackage->sfrac;
645 			ltfrac = pspanpackage->tfrac;
646 			llight = pspanpackage->light;
647 			lzi = pspanpackage->zi;
648 
649 			do
650 			{
651 				if ((lzi >> 16) >= *lpz)
652 				{
653 					*lpdest = ((byte *)acolormap)[*lptex + (llight & 0xFF00)];
654 // gel mapping					*lpdest = gelmap[*lpdest];
655 					*lpz = lzi >> 16;
656 				}
657 				lpdest++;
658 				lzi += r_zistepx;
659 				lpz++;
660 				llight += r_lstepx;
661 				lptex += a_ststepxwhole;
662 				lsfrac += a_sstepxfrac;
663 				lptex += lsfrac >> 16;
664 				lsfrac &= 0xFFFF;
665 				ltfrac += a_tstepxfrac;
666 				if (ltfrac & 0x10000)
667 				{
668 					lptex += r_affinetridesc.skinwidth;
669 					ltfrac &= 0xFFFF;
670 				}
671 			} while (--lcount);
672 		}
673 
674 		pspanpackage++;
675 	} while (pspanpackage->count != -999999);
676 }
677 #endif	// !id386
678 
679 
680 /*
681 ================
682 D_PolysetFillSpans8
683 ================
684 */
D_PolysetFillSpans8(spanpackage_t * pspanpackage)685 void D_PolysetFillSpans8 (spanpackage_t *pspanpackage)
686 {
687 	int				color;
688 
689 // FIXME: do z buffering
690 
691 	color = d_aflatcolor++;
692 
693 	while (1)
694 	{
695 		int		lcount;
696 		byte	*lpdest;
697 
698 		lcount = pspanpackage->count;
699 
700 		if (lcount == -1)
701 			return;
702 
703 		if (lcount)
704 		{
705 			lpdest = pspanpackage->pdest;
706 
707 			do
708 			{
709 				*lpdest++ = color;
710 			} while (--lcount);
711 		}
712 
713 		pspanpackage++;
714 	}
715 }
716 
717 /*
718 ================
719 D_RasterizeAliasPolySmooth
720 ================
721 */
D_RasterizeAliasPolySmooth(void)722 void D_RasterizeAliasPolySmooth (void)
723 {
724 	int				initialleftheight, initialrightheight;
725 	int				*plefttop, *prighttop, *pleftbottom, *prightbottom;
726 	int				working_lstepx, originalcount;
727 
728 	plefttop = pedgetable->pleftedgevert0;
729 	prighttop = pedgetable->prightedgevert0;
730 
731 	pleftbottom = pedgetable->pleftedgevert1;
732 	prightbottom = pedgetable->prightedgevert1;
733 
734 	initialleftheight = pleftbottom[1] - plefttop[1];
735 	initialrightheight = prightbottom[1] - prighttop[1];
736 
737 //
738 // set the s, t, and light gradients, which are consistent across the triangle
739 // because being a triangle, things are affine
740 //
741 	D_PolysetCalcGradients (r_affinetridesc.skinwidth);
742 
743 //
744 // rasterize the polygon
745 //
746 
747 //
748 // scan out the top (and possibly only) part of the left edge
749 //
750 	d_pedgespanpackage = a_spans;
751 
752 	ystart = plefttop[1];
753 	d_aspancount = plefttop[0] - prighttop[0];
754 
755 	d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
756 			(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
757 #if	id386
758 	d_sfrac = (plefttop[2] & 0xFFFF) << 16;
759 	d_tfrac = (plefttop[3] & 0xFFFF) << 16;
760 #else
761 	d_sfrac = plefttop[2] & 0xFFFF;
762 	d_tfrac = plefttop[3] & 0xFFFF;
763 #endif
764 	d_light = plefttop[4];
765 	d_zi = plefttop[5];
766 
767 	d_pdest = (byte *)d_viewbuffer +
768 			ystart * screenwidth + plefttop[0];
769 	d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
770 
771 	if (initialleftheight == 1)
772 	{
773 		d_pedgespanpackage->pdest = d_pdest;
774 		d_pedgespanpackage->pz = d_pz;
775 		d_pedgespanpackage->count = d_aspancount;
776 		d_pedgespanpackage->ptex = d_ptex;
777 
778 		d_pedgespanpackage->sfrac = d_sfrac;
779 		d_pedgespanpackage->tfrac = d_tfrac;
780 
781 	// FIXME: need to clamp l, s, t, at both ends?
782 		d_pedgespanpackage->light = d_light;
783 		d_pedgespanpackage->zi = d_zi;
784 
785 		d_pedgespanpackage++;
786 	}
787 	else
788 	{
789 		D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
790 							  pleftbottom[0], pleftbottom[1]);
791 
792 	#if	id386
793 		d_pzbasestep = (d_zwidth + ubasestep) << 1;
794 		d_pzextrastep = d_pzbasestep + 2;
795 	#else
796 		d_pzbasestep = d_zwidth + ubasestep;
797 		d_pzextrastep = d_pzbasestep + 1;
798 	#endif
799 
800 		d_pdestbasestep = screenwidth + ubasestep;
801 		d_pdestextrastep = d_pdestbasestep + 1;
802 
803 	// TODO: can reuse partial expressions here
804 
805 	// for negative steps in x along left edge, bias toward overflow rather than
806 	// underflow (sort of turning the floor () we did in the gradient calcs into
807 	// ceil (), but plus a little bit)
808 		if (ubasestep < 0)
809 			working_lstepx = r_lstepx - 1;
810 		else
811 			working_lstepx = r_lstepx;
812 
813 		d_countextrastep = ubasestep + 1;
814 		d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
815 				((r_tstepy + r_tstepx * ubasestep) >> 16) *
816 				r_affinetridesc.skinwidth;
817 	#if	id386
818 		d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
819 		d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
820 	#else
821 		d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
822 		d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
823 	#endif
824 		d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
825 		d_zibasestep = r_zistepy + r_zistepx * ubasestep;
826 
827 		d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
828 				((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
829 				r_affinetridesc.skinwidth;
830 	#if	id386
831 		d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16;
832 		d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16;
833 	#else
834 		d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF;
835 		d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF;
836 	#endif
837 		d_lightextrastep = d_lightbasestep + working_lstepx;
838 		d_ziextrastep = d_zibasestep + r_zistepx;
839 
840 		D_PolysetScanLeftEdge (initialleftheight);
841 	}
842 
843 //
844 // scan out the bottom part of the left edge, if it exists
845 //
846 	if (pedgetable->numleftedges == 2)
847 	{
848 		int		height;
849 
850 		plefttop = pleftbottom;
851 		pleftbottom = pedgetable->pleftedgevert2;
852 
853 		height = pleftbottom[1] - plefttop[1];
854 
855 // TODO: make this a function; modularize this function in general
856 
857 		ystart = plefttop[1];
858 		d_aspancount = plefttop[0] - prighttop[0];
859 		d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
860 				(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
861 		d_sfrac = 0;
862 		d_tfrac = 0;
863 		d_light = plefttop[4];
864 		d_zi = plefttop[5];
865 
866 		d_pdest = (byte *)d_viewbuffer + ystart * screenwidth + plefttop[0];
867 		d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
868 
869 		if (height == 1)
870 		{
871 			d_pedgespanpackage->pdest = d_pdest;
872 			d_pedgespanpackage->pz = d_pz;
873 			d_pedgespanpackage->count = d_aspancount;
874 			d_pedgespanpackage->ptex = d_ptex;
875 
876 			d_pedgespanpackage->sfrac = d_sfrac;
877 			d_pedgespanpackage->tfrac = d_tfrac;
878 
879 		// FIXME: need to clamp l, s, t, at both ends?
880 			d_pedgespanpackage->light = d_light;
881 			d_pedgespanpackage->zi = d_zi;
882 
883 			d_pedgespanpackage++;
884 		}
885 		else
886 		{
887 			D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
888 								  pleftbottom[0], pleftbottom[1]);
889 
890 			d_pdestbasestep = screenwidth + ubasestep;
891 			d_pdestextrastep = d_pdestbasestep + 1;
892 
893 	#if	id386
894 			d_pzbasestep = (d_zwidth + ubasestep) << 1;
895 			d_pzextrastep = d_pzbasestep + 2;
896 	#else
897 			d_pzbasestep = d_zwidth + ubasestep;
898 			d_pzextrastep = d_pzbasestep + 1;
899 	#endif
900 
901 			if (ubasestep < 0)
902 				working_lstepx = r_lstepx - 1;
903 			else
904 				working_lstepx = r_lstepx;
905 
906 			d_countextrastep = ubasestep + 1;
907 			d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
908 					((r_tstepy + r_tstepx * ubasestep) >> 16) *
909 					r_affinetridesc.skinwidth;
910 	#if	id386
911 			d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
912 			d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
913 	#else
914 			d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
915 			d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
916 	#endif
917 			d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
918 			d_zibasestep = r_zistepy + r_zistepx * ubasestep;
919 
920 			d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
921 					((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
922 					r_affinetridesc.skinwidth;
923 	#if	id386
924 			d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16;
925 			d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16;
926 	#else
927 			d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF;
928 			d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF;
929 	#endif
930 			d_lightextrastep = d_lightbasestep + working_lstepx;
931 			d_ziextrastep = d_zibasestep + r_zistepx;
932 
933 			D_PolysetScanLeftEdge (height);
934 		}
935 	}
936 
937 // scan out the top (and possibly only) part of the right edge, updating the
938 // count field
939 	d_pedgespanpackage = a_spans;
940 
941 	D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
942 						  prightbottom[0], prightbottom[1]);
943 	d_aspancount = 0;
944 	d_countextrastep = ubasestep + 1;
945 	originalcount = a_spans[initialrightheight].count;
946 	a_spans[initialrightheight].count = -999999; // mark end of the spanpackages
947 	D_PolysetDrawSpans8 (a_spans);
948 
949 // scan out the bottom part of the right edge, if it exists
950 	if (pedgetable->numrightedges == 2)
951 	{
952 		int				height;
953 		spanpackage_t	*pstart;
954 
955 		pstart = a_spans + initialrightheight;
956 		pstart->count = originalcount;
957 
958 		d_aspancount = prightbottom[0] - prighttop[0];
959 
960 		prighttop = prightbottom;
961 		prightbottom = pedgetable->prightedgevert2;
962 
963 		height = prightbottom[1] - prighttop[1];
964 
965 		D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
966 							  prightbottom[0], prightbottom[1]);
967 
968 		d_countextrastep = ubasestep + 1;
969 		a_spans[initialrightheight + height].count = -999999;
970 											// mark end of the spanpackages
971 		D_PolysetDrawSpans8 (pstart);
972 	}
973 }
974 
975 
976 /*
977 ================
978 D_PolysetSetEdgeTable
979 ================
980 */
D_PolysetSetEdgeTable(void)981 void D_PolysetSetEdgeTable (void)
982 {
983 	int			edgetableindex;
984 
985 	edgetableindex = 0;	// assume the vertices are already in
986 						//  top to bottom order
987 
988 //
989 // determine which edges are right & left, and the order in which
990 // to rasterize them
991 //
992 	if (r_p0[1] >= r_p1[1])
993 	{
994 		if (r_p0[1] == r_p1[1])
995 		{
996 			if (r_p0[1] < r_p2[1])
997 				pedgetable = &edgetables[2];
998 			else
999 				pedgetable = &edgetables[5];
1000 
1001 			return;
1002 		}
1003 		else
1004 		{
1005 			edgetableindex = 1;
1006 		}
1007 	}
1008 
1009 	if (r_p0[1] == r_p2[1])
1010 	{
1011 		if (edgetableindex)
1012 			pedgetable = &edgetables[8];
1013 		else
1014 			pedgetable = &edgetables[9];
1015 
1016 		return;
1017 	}
1018 	else if (r_p1[1] == r_p2[1])
1019 	{
1020 		if (edgetableindex)
1021 			pedgetable = &edgetables[10];
1022 		else
1023 			pedgetable = &edgetables[11];
1024 
1025 		return;
1026 	}
1027 
1028 	if (r_p0[1] > r_p2[1])
1029 		edgetableindex += 2;
1030 
1031 	if (r_p1[1] > r_p2[1])
1032 		edgetableindex += 4;
1033 
1034 	pedgetable = &edgetables[edgetableindex];
1035 }
1036 
1037 
1038 #if 0
1039 
1040 void D_PolysetRecursiveDrawLine (int *lp1, int *lp2)
1041 {
1042 	int		d;
1043 	int		new[6];
1044 	int 	ofs;
1045 
1046 	d = lp2[0] - lp1[0];
1047 	if (d < -1 || d > 1)
1048 		goto split;
1049 	d = lp2[1] - lp1[1];
1050 	if (d < -1 || d > 1)
1051 		goto split;
1052 
1053 	return;	// line is completed
1054 
1055 split:
1056 // split this edge
1057 	new[0] = (lp1[0] + lp2[0]) >> 1;
1058 	new[1] = (lp1[1] + lp2[1]) >> 1;
1059 	new[5] = (lp1[5] + lp2[5]) >> 1;
1060 	new[2] = (lp1[2] + lp2[2]) >> 1;
1061 	new[3] = (lp1[3] + lp2[3]) >> 1;
1062 	new[4] = (lp1[4] + lp2[4]) >> 1;
1063 
1064 // draw the point
1065 	ofs = d_scantable[new[1]] + new[0];
1066 	if (new[5] > d_pzbuffer[ofs])
1067 	{
1068 		int		pix;
1069 
1070 		d_pzbuffer[ofs] = new[5];
1071 		pix = skintable[new[3]>>16][new[2]>>16];
1072 //		pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)];
1073 		d_viewbuffer[ofs] = pix;
1074 	}
1075 
1076 // recursively continue
1077 	D_PolysetRecursiveDrawLine (lp1, new);
1078 	D_PolysetRecursiveDrawLine (new, lp2);
1079 }
1080 
1081 void D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3)
1082 {
1083 	int		d;
1084 	int		new[4];
1085 
1086 	d = lp2[0] - lp1[0];
1087 	if (d < -1 || d > 1)
1088 		goto split;
1089 	d = lp2[1] - lp1[1];
1090 	if (d < -1 || d > 1)
1091 		goto split;
1092 	return;
1093 
1094 split:
1095 // split this edge
1096 	new[0] = (lp1[0] + lp2[0]) >> 1;
1097 	new[1] = (lp1[1] + lp2[1]) >> 1;
1098 	new[5] = (lp1[5] + lp2[5]) >> 1;
1099 	new[2] = (lp1[2] + lp2[2]) >> 1;
1100 	new[3] = (lp1[3] + lp2[3]) >> 1;
1101 	new[4] = (lp1[4] + lp2[4]) >> 1;
1102 
1103 	D_PolysetRecursiveDrawLine (new, lp3);
1104 
1105 // recursively continue
1106 	D_PolysetRecursiveTriangle (lp1, new, lp3);
1107 	D_PolysetRecursiveTriangle (new, lp2, lp3);
1108 }
1109 
1110 #endif
1111 
1112