|
|
1.1 root 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: */
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: */
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: */
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: */
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: */
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: */
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: */
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: */
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: */
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];
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: */
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: */
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: */
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: */
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.