• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 byte gelmap[256];
InitGel(byte * palette)591 void InitGel (byte *palette)
592 {
593 	int		i;
594 	int		r;
595 
596 	for (i=0 ; i<256 ; i++)
597 	{
598 //		r = (palette[i*3]>>4);
599 		r = (palette[i*3] + palette[i*3+1] + palette[i*3+2])/(16*3);
600 		gelmap[i] = /* 64 */ 0 + r;
601 	}
602 }
603 
604 
605 #if	!id386
606 
607 /*
608 ================
609 D_PolysetDrawSpans8
610 ================
611 */
D_PolysetDrawSpans8(spanpackage_t * pspanpackage)612 void D_PolysetDrawSpans8 (spanpackage_t *pspanpackage)
613 {
614 	int		lcount;
615 	byte	*lpdest;
616 	byte	*lptex;
617 	int		lsfrac, ltfrac;
618 	int		llight;
619 	int		lzi;
620 	short	*lpz;
621 
622 	do
623 	{
624 		lcount = d_aspancount - pspanpackage->count;
625 
626 		errorterm += erroradjustup;
627 		if (errorterm >= 0)
628 		{
629 			d_aspancount += d_countextrastep;
630 			errorterm -= erroradjustdown;
631 		}
632 		else
633 		{
634 			d_aspancount += ubasestep;
635 		}
636 
637 		if (lcount)
638 		{
639 			lpdest = pspanpackage->pdest;
640 			lptex = pspanpackage->ptex;
641 			lpz = pspanpackage->pz;
642 			lsfrac = pspanpackage->sfrac;
643 			ltfrac = pspanpackage->tfrac;
644 			llight = pspanpackage->light;
645 			lzi = pspanpackage->zi;
646 
647 			do
648 			{
649 				if ((lzi >> 16) >= *lpz)
650 				{
651 					*lpdest = ((byte *)acolormap)[*lptex + (llight & 0xFF00)];
652 // gel mapping					*lpdest = gelmap[*lpdest];
653 					*lpz = lzi >> 16;
654 				}
655 				lpdest++;
656 				lzi += r_zistepx;
657 				lpz++;
658 				llight += r_lstepx;
659 				lptex += a_ststepxwhole;
660 				lsfrac += a_sstepxfrac;
661 				lptex += lsfrac >> 16;
662 				lsfrac &= 0xFFFF;
663 				ltfrac += a_tstepxfrac;
664 				if (ltfrac & 0x10000)
665 				{
666 					lptex += r_affinetridesc.skinwidth;
667 					ltfrac &= 0xFFFF;
668 				}
669 			} while (--lcount);
670 		}
671 
672 		pspanpackage++;
673 	} while (pspanpackage->count != -999999);
674 }
675 #endif	// !id386
676 
677 
678 /*
679 ================
680 D_PolysetFillSpans8
681 ================
682 */
D_PolysetFillSpans8(spanpackage_t * pspanpackage)683 void D_PolysetFillSpans8 (spanpackage_t *pspanpackage)
684 {
685 	int				color;
686 
687 // FIXME: do z buffering
688 
689 	color = d_aflatcolor++;
690 
691 	while (1)
692 	{
693 		int		lcount;
694 		byte	*lpdest;
695 
696 		lcount = pspanpackage->count;
697 
698 		if (lcount == -1)
699 			return;
700 
701 		if (lcount)
702 		{
703 			lpdest = pspanpackage->pdest;
704 
705 			do
706 			{
707 				*lpdest++ = color;
708 			} while (--lcount);
709 		}
710 
711 		pspanpackage++;
712 	}
713 }
714 
715 /*
716 ================
717 D_RasterizeAliasPolySmooth
718 ================
719 */
D_RasterizeAliasPolySmooth(void)720 void D_RasterizeAliasPolySmooth (void)
721 {
722 	int				initialleftheight, initialrightheight;
723 	int				*plefttop, *prighttop, *pleftbottom, *prightbottom;
724 	int				working_lstepx, originalcount;
725 
726 	plefttop = pedgetable->pleftedgevert0;
727 	prighttop = pedgetable->prightedgevert0;
728 
729 	pleftbottom = pedgetable->pleftedgevert1;
730 	prightbottom = pedgetable->prightedgevert1;
731 
732 	initialleftheight = pleftbottom[1] - plefttop[1];
733 	initialrightheight = prightbottom[1] - prighttop[1];
734 
735 //
736 // set the s, t, and light gradients, which are consistent across the triangle
737 // because being a triangle, things are affine
738 //
739 	D_PolysetCalcGradients (r_affinetridesc.skinwidth);
740 
741 //
742 // rasterize the polygon
743 //
744 
745 //
746 // scan out the top (and possibly only) part of the left edge
747 //
748 	D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
749 						  pleftbottom[0], pleftbottom[1]);
750 
751 	d_pedgespanpackage = a_spans;
752 
753 	ystart = plefttop[1];
754 	d_aspancount = plefttop[0] - prighttop[0];
755 
756 	d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
757 			(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
758 #if	id386
759 	d_sfrac = (plefttop[2] & 0xFFFF) << 16;
760 	d_tfrac = (plefttop[3] & 0xFFFF) << 16;
761 	d_pzbasestep = (d_zwidth + ubasestep) << 1;
762 	d_pzextrastep = d_pzbasestep + 2;
763 #else
764 	d_sfrac = plefttop[2] & 0xFFFF;
765 	d_tfrac = plefttop[3] & 0xFFFF;
766 	d_pzbasestep = d_zwidth + ubasestep;
767 	d_pzextrastep = d_pzbasestep + 1;
768 #endif
769 	d_light = plefttop[4];
770 	d_zi = plefttop[5];
771 
772 	d_pdestbasestep = screenwidth + ubasestep;
773 	d_pdestextrastep = d_pdestbasestep + 1;
774 	d_pdest = (byte *)d_viewbuffer +
775 			ystart * screenwidth + plefttop[0];
776 	d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
777 
778 // TODO: can reuse partial expressions here
779 
780 // for negative steps in x along left edge, bias toward overflow rather than
781 // underflow (sort of turning the floor () we did in the gradient calcs into
782 // ceil (), but plus a little bit)
783 	if (ubasestep < 0)
784 		working_lstepx = r_lstepx - 1;
785 	else
786 		working_lstepx = r_lstepx;
787 
788 	d_countextrastep = ubasestep + 1;
789 	d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
790 			((r_tstepy + r_tstepx * ubasestep) >> 16) *
791 			r_affinetridesc.skinwidth;
792 #if	id386
793 	d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
794 	d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
795 #else
796 	d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
797 	d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
798 #endif
799 	d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
800 	d_zibasestep = r_zistepy + r_zistepx * ubasestep;
801 
802 	d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
803 			((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
804 			r_affinetridesc.skinwidth;
805 #if	id386
806 	d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) << 16;
807 	d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) << 16;
808 #else
809 	d_sfracextrastep = (r_sstepy + r_sstepx*d_countextrastep) & 0xFFFF;
810 	d_tfracextrastep = (r_tstepy + r_tstepx*d_countextrastep) & 0xFFFF;
811 #endif
812 	d_lightextrastep = d_lightbasestep + working_lstepx;
813 	d_ziextrastep = d_zibasestep + r_zistepx;
814 
815 	D_PolysetScanLeftEdge (initialleftheight);
816 
817 //
818 // scan out the bottom part of the left edge, if it exists
819 //
820 	if (pedgetable->numleftedges == 2)
821 	{
822 		int		height;
823 
824 		plefttop = pleftbottom;
825 		pleftbottom = pedgetable->pleftedgevert2;
826 
827 		D_PolysetSetUpForLineScan(plefttop[0], plefttop[1],
828 							  pleftbottom[0], pleftbottom[1]);
829 
830 		height = pleftbottom[1] - plefttop[1];
831 
832 // TODO: make this a function; modularize this function in general
833 
834 		ystart = plefttop[1];
835 		d_aspancount = plefttop[0] - prighttop[0];
836 		d_ptex = (byte *)r_affinetridesc.pskin + (plefttop[2] >> 16) +
837 				(plefttop[3] >> 16) * r_affinetridesc.skinwidth;
838 		d_sfrac = 0;
839 		d_tfrac = 0;
840 		d_light = plefttop[4];
841 		d_zi = plefttop[5];
842 
843 		d_pdestbasestep = screenwidth + ubasestep;
844 		d_pdestextrastep = d_pdestbasestep + 1;
845 		d_pdest = (byte *)d_viewbuffer + ystart * screenwidth + plefttop[0];
846 #if	id386
847 		d_pzbasestep = (d_zwidth + ubasestep) << 1;
848 		d_pzextrastep = d_pzbasestep + 2;
849 #else
850 		d_pzbasestep = d_zwidth + ubasestep;
851 		d_pzextrastep = d_pzbasestep + 1;
852 #endif
853 		d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
854 
855 		if (ubasestep < 0)
856 			working_lstepx = r_lstepx - 1;
857 		else
858 			working_lstepx = r_lstepx;
859 
860 		d_countextrastep = ubasestep + 1;
861 		d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
862 				((r_tstepy + r_tstepx * ubasestep) >> 16) *
863 				r_affinetridesc.skinwidth;
864 #if	id386
865 		d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
866 		d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
867 #else
868 		d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
869 		d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
870 #endif
871 		d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
872 		d_zibasestep = r_zistepy + r_zistepx * ubasestep;
873 
874 		d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
875 				((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
876 				r_affinetridesc.skinwidth;
877 #if	id386
878 		d_sfracextrastep = ((r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF)<<16;
879 		d_tfracextrastep = ((r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF)<<16;
880 #else
881 		d_sfracextrastep = (r_sstepy+r_sstepx*d_countextrastep) & 0xFFFF;
882 		d_tfracextrastep = (r_tstepy+r_tstepx*d_countextrastep) & 0xFFFF;
883 #endif
884 		d_lightextrastep = d_lightbasestep + working_lstepx;
885 		d_ziextrastep = d_zibasestep + r_zistepx;
886 
887 		D_PolysetScanLeftEdge (height);
888 	}
889 
890 // scan out the top (and possibly only) part of the right edge, updating the
891 // count field
892 	d_pedgespanpackage = a_spans;
893 
894 	D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
895 						  prightbottom[0], prightbottom[1]);
896 	d_aspancount = 0;
897 	d_countextrastep = ubasestep + 1;
898 	originalcount = a_spans[initialrightheight].count;
899 	a_spans[initialrightheight].count = -999999; // mark end of the spanpackages
900 	D_PolysetDrawSpans8 (a_spans);
901 
902 // scan out the bottom part of the right edge, if it exists
903 	if (pedgetable->numrightedges == 2)
904 	{
905 		int				height;
906 		spanpackage_t	*pstart;
907 
908 		pstart = a_spans + initialrightheight;
909 		pstart->count = originalcount;
910 
911 		d_aspancount = prightbottom[0] - prighttop[0];
912 
913 		prighttop = prightbottom;
914 		prightbottom = pedgetable->prightedgevert2;
915 
916 		height = prightbottom[1] - prighttop[1];
917 
918 		D_PolysetSetUpForLineScan(prighttop[0], prighttop[1],
919 							  prightbottom[0], prightbottom[1]);
920 
921 		d_countextrastep = ubasestep + 1;
922 		a_spans[initialrightheight + height].count = -999999;
923 											// mark end of the spanpackages
924 		D_PolysetDrawSpans8 (pstart);
925 	}
926 }
927 
928 
929 /*
930 ================
931 D_PolysetSetEdgeTable
932 ================
933 */
D_PolysetSetEdgeTable(void)934 void D_PolysetSetEdgeTable (void)
935 {
936 	int			edgetableindex;
937 
938 	edgetableindex = 0;	// assume the vertices are already in
939 						//  top to bottom order
940 
941 //
942 // determine which edges are right & left, and the order in which
943 // to rasterize them
944 //
945 	if (r_p0[1] >= r_p1[1])
946 	{
947 		if (r_p0[1] == r_p1[1])
948 		{
949 			if (r_p0[1] < r_p2[1])
950 				pedgetable = &edgetables[2];
951 			else
952 				pedgetable = &edgetables[5];
953 
954 			return;
955 		}
956 		else
957 		{
958 			edgetableindex = 1;
959 		}
960 	}
961 
962 	if (r_p0[1] == r_p2[1])
963 	{
964 		if (edgetableindex)
965 			pedgetable = &edgetables[8];
966 		else
967 			pedgetable = &edgetables[9];
968 
969 		return;
970 	}
971 	else if (r_p1[1] == r_p2[1])
972 	{
973 		if (edgetableindex)
974 			pedgetable = &edgetables[10];
975 		else
976 			pedgetable = &edgetables[11];
977 
978 		return;
979 	}
980 
981 	if (r_p0[1] > r_p2[1])
982 		edgetableindex += 2;
983 
984 	if (r_p1[1] > r_p2[1])
985 		edgetableindex += 4;
986 
987 	pedgetable = &edgetables[edgetableindex];
988 }
989 
990 
991 #if 0
992 
993 void D_PolysetRecursiveDrawLine (int *lp1, int *lp2)
994 {
995 	int		d;
996 	int		new[6];
997 	int 	ofs;
998 
999 	d = lp2[0] - lp1[0];
1000 	if (d < -1 || d > 1)
1001 		goto split;
1002 	d = lp2[1] - lp1[1];
1003 	if (d < -1 || d > 1)
1004 		goto split;
1005 
1006 	return;	// line is completed
1007 
1008 split:
1009 // split this edge
1010 	new[0] = (lp1[0] + lp2[0]) >> 1;
1011 	new[1] = (lp1[1] + lp2[1]) >> 1;
1012 	new[5] = (lp1[5] + lp2[5]) >> 1;
1013 	new[2] = (lp1[2] + lp2[2]) >> 1;
1014 	new[3] = (lp1[3] + lp2[3]) >> 1;
1015 	new[4] = (lp1[4] + lp2[4]) >> 1;
1016 
1017 // draw the point
1018 	ofs = d_scantable[new[1]] + new[0];
1019 	if (new[5] > d_pzbuffer[ofs])
1020 	{
1021 		int		pix;
1022 
1023 		d_pzbuffer[ofs] = new[5];
1024 		pix = skintable[new[3]>>16][new[2]>>16];
1025 //		pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)];
1026 		d_viewbuffer[ofs] = pix;
1027 	}
1028 
1029 // recursively continue
1030 	D_PolysetRecursiveDrawLine (lp1, new);
1031 	D_PolysetRecursiveDrawLine (new, lp2);
1032 }
1033 
1034 void D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3)
1035 {
1036 	int		d;
1037 	int		new[4];
1038 
1039 	d = lp2[0] - lp1[0];
1040 	if (d < -1 || d > 1)
1041 		goto split;
1042 	d = lp2[1] - lp1[1];
1043 	if (d < -1 || d > 1)
1044 		goto split;
1045 	return;
1046 
1047 split:
1048 // split this edge
1049 	new[0] = (lp1[0] + lp2[0]) >> 1;
1050 	new[1] = (lp1[1] + lp2[1]) >> 1;
1051 	new[5] = (lp1[5] + lp2[5]) >> 1;
1052 	new[2] = (lp1[2] + lp2[2]) >> 1;
1053 	new[3] = (lp1[3] + lp2[3]) >> 1;
1054 	new[4] = (lp1[4] + lp2[4]) >> 1;
1055 
1056 	D_PolysetRecursiveDrawLine (new, lp3);
1057 
1058 // recursively continue
1059 	D_PolysetRecursiveTriangle (lp1, new, lp3);
1060 	D_PolysetRecursiveTriangle (new, lp2, lp3);
1061 }
1062 
1063 #endif
1064 
1065