|
|
1.1 root 1: // R_things.c
2: #include <stdio.h>
3: #include <stdlib.h>
4: #include "DoomDef.h"
5: #include "R_local.h"
6:
7: void R_DrawColumn (void);
8: void R_DrawFuzzColumn (void);
9:
10: typedef struct
11: {
12: int x1, x2;
13:
14: int column;
15: int topclip;
16: int bottomclip;
17: } maskdraw_t;
18:
19: /*
20:
21: Sprite rotation 0 is facing the viewer, rotation 1 is one angle turn CLOCKWISE around the axis.
22: This is not the same as the angle, which increases counter clockwise
23: (protractor). There was a lot of stuff grabbed wrong, so I changed it...
24:
25: */
26:
27:
28: fixed_t pspritescale, pspriteiscale;
29:
30: lighttable_t **spritelights;
31:
32: // constant arrays used for psprite clipping and initializing clipping
33: short negonearray[SCREENWIDTH];
34: short screenheightarray[SCREENWIDTH];
35:
36: /*
37: ===============================================================================
38:
39: INITIALIZATION FUNCTIONS
40:
41: ===============================================================================
42: */
43:
44: // variables used to look up and range check thing_t sprites patches
45: spritedef_t *sprites;
46: int numsprites;
47:
48: spriteframe_t sprtemp[26];
49: int maxframe;
50: char *spritename;
51:
52:
53:
54: /*
55: =================
56: =
57: = R_InstallSpriteLump
58: =
59: = Local function for R_InitSprites
60: =================
61: */
62:
63: void R_InstallSpriteLump (int lump, unsigned frame, unsigned rotation, boolean flipped)
64: {
65: int r;
66:
67: if (frame >= 26 || rotation > 8)
68: I_Error ("R_InstallSpriteLump: Bad frame characters in lump %i", lump);
69:
70: if ((int)frame > maxframe)
71: maxframe = frame;
72:
73: if (rotation == 0)
74: {
75: // the lump should be used for all rotations
76: if (sprtemp[frame].rotate == false)
77: I_Error ("R_InitSprites: Sprite %s frame %c has multip rot=0 lump"
78: , spritename, 'A'+frame);
79: if (sprtemp[frame].rotate == true)
80: I_Error ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump"
81: , spritename, 'A'+frame);
82:
83: sprtemp[frame].rotate = false;
84: for (r=0 ; r<8 ; r++)
85: {
86: sprtemp[frame].lump[r] = lump - firstspritelump;
87: sprtemp[frame].flip[r] = (byte)flipped;
88: }
89: return;
90: }
91:
92: // the lump is only used for one rotation
93: if (sprtemp[frame].rotate == false)
94: I_Error ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump"
95: , spritename, 'A'+frame);
96:
97: sprtemp[frame].rotate = true;
98:
99: rotation--; // make 0 based
100: if (sprtemp[frame].lump[rotation] != -1)
101: I_Error ("R_InitSprites: Sprite %s : %c : %c has two lumps mapped to it"
102: ,spritename, 'A'+frame, '1'+rotation);
103:
104: sprtemp[frame].lump[rotation] = lump - firstspritelump;
105: sprtemp[frame].flip[rotation] = (byte)flipped;
106: }
107:
108: /*
109: =================
110: =
111: = R_InitSpriteDefs
112: =
113: = Pass a null terminated list of sprite names (4 chars exactly) to be used
114: = Builds the sprite rotation matrixes to account for horizontally flipped
115: = sprites. Will report an error if the lumps are inconsistant
116: =
117: Only called at startup
118: =
119: = Sprite lump names are 4 characters for the actor, a letter for the frame,
120: = and a number for the rotation, A sprite that is flippable will have an
121: = additional letter/number appended. The rotation character can be 0 to
122: = signify no rotations
123: =================
124: */
125:
126: void R_InitSpriteDefs (char **namelist)
127: {
128: char **check;
129: int i, l, intname, frame, rotation;
130: int start, end;
131:
132: // count the number of sprite names
133: check = namelist;
134: while (*check != NULL)
135: check++;
136: numsprites = check-namelist;
137:
138: if (!numsprites)
139: return;
140:
141: sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL);
142:
143: start = firstspritelump-1;
144: end = lastspritelump+1;
145:
146: // scan all the lump names for each of the names, noting the highest
147: // frame letter
148: // Just compare 4 characters as ints
149: for (i=0 ; i<numsprites ; i++)
150: {
151: spritename = namelist[i];
152: memset (sprtemp,-1, sizeof(sprtemp));
153:
154: maxframe = -1;
155: intname = *(int *)namelist[i];
156:
157: //
158: // scan the lumps, filling in the frames for whatever is found
159: //
160: for (l=start+1 ; l<end ; l++)
161: if (*(int *)lumpinfo[l].name == intname)
162: {
163: frame = lumpinfo[l].name[4] - 'A';
164: rotation = lumpinfo[l].name[5] - '0';
165: R_InstallSpriteLump (l, frame, rotation, false);
166: if (lumpinfo[l].name[6])
167: {
168: frame = lumpinfo[l].name[6] - 'A';
169: rotation = lumpinfo[l].name[7] - '0';
170: R_InstallSpriteLump (l, frame, rotation, true);
171: }
172: }
173:
174: //
175: // check the frames that were found for completeness
176: //
177: if (maxframe == -1)
178: {
179: //continue;
180: sprites[i].numframes = 0;
181: if (shareware)
182: continue;
183: I_Error ("R_InitSprites: No lumps found for sprite %s"
184: ,namelist[i]);
185: }
186:
187: maxframe++;
188: for (frame = 0 ; frame < maxframe ; frame++)
189: {
190: switch ((int)sprtemp[frame].rotate)
191: {
192: case -1: // no rotations were found for that frame at all
193: I_Error ("R_InitSprites: No patches found for %s frame %c"
194: , namelist[i], frame+'A');
195: case 0: // only the first rotation is needed
196: break;
197:
198: case 1: // must have all 8 frames
199: for (rotation=0 ; rotation<8 ; rotation++)
200: if (sprtemp[frame].lump[rotation] == -1)
201: I_Error ("R_InitSprites: Sprite %s frame %c is missing rotations"
202: , namelist[i], frame+'A');
203: }
204: }
205:
206: //
207: // allocate space for the frames present and copy sprtemp to it
208: //
209: sprites[i].numframes = maxframe;
210: sprites[i].spriteframes =
211: Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
212: memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t));
213: }
214:
215: }
216:
217:
218: /*
219: ===============================================================================
220:
221: GAME FUNCTIONS
222:
223: ===============================================================================
224: */
225:
226: vissprite_t vissprites[MAXVISSPRITES], *vissprite_p;
227: int newvissprite;
228:
229:
230: /*
231: ===================
232: =
233: = R_InitSprites
234: =
235: = Called at program start
236: ===================
237: */
238:
239: void R_InitSprites (char **namelist)
240: {
241: int i;
242:
243: for (i=0 ; i<SCREENWIDTH ; i++)
244: {
245: negonearray[i] = -1;
246: }
247:
248: R_InitSpriteDefs (namelist);
249: }
250:
251:
252: /*
253: ===================
254: =
255: = R_ClearSprites
256: =
257: = Called at frame start
258: ===================
259: */
260:
261: void R_ClearSprites (void)
262: {
263: vissprite_p = vissprites;
264: }
265:
266:
267: /*
268: ===================
269: =
270: = R_NewVisSprite
271: =
272: ===================
273: */
274:
275: vissprite_t overflowsprite;
276:
277: vissprite_t *R_NewVisSprite (void)
278: {
279: if (vissprite_p == &vissprites[MAXVISSPRITES])
280: return &overflowsprite;
281: vissprite_p++;
282: return vissprite_p-1;
283: }
284:
285:
286: /*
287: ================
288: =
289: = R_DrawMaskedColumn
290: =
291: = Used for sprites and masked mid textures
292: ================
293: */
294:
295: short *mfloorclip;
296: short *mceilingclip;
297: fixed_t spryscale;
298: fixed_t sprtopscreen;
299: fixed_t sprbotscreen;
300:
301: void R_DrawMaskedColumn (column_t *column, signed int baseclip)
302: {
303: int topscreen, bottomscreen;
304: fixed_t basetexturemid;
305:
306: basetexturemid = dc_texturemid;
307:
308: for ( ; column->topdelta != 0xff ; )
309: {
310: // calculate unclipped screen coordinates for post
311: topscreen = sprtopscreen + spryscale*column->topdelta;
312: bottomscreen = topscreen + spryscale*column->length;
313: dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
314: dc_yh = (bottomscreen-1)>>FRACBITS;
315:
316: if (dc_yh >= mfloorclip[dc_x])
317: dc_yh = mfloorclip[dc_x]-1;
318: if (dc_yl <= mceilingclip[dc_x])
319: dc_yl = mceilingclip[dc_x]+1;
320:
321: if(dc_yh >= baseclip && baseclip != -1)
322: dc_yh = baseclip;
323:
324: if (dc_yl <= dc_yh)
325: {
326: dc_source = (byte *)column + 3;
327: dc_texturemid = basetexturemid - (column->topdelta<<FRACBITS);
328: // dc_source = (byte *)column + 3 - column->topdelta;
329: colfunc (); // either R_DrawColumn or R_DrawFuzzColumn
330: }
331: column = (column_t *)( (byte *)column + column->length + 4);
332: }
333:
334: dc_texturemid = basetexturemid;
335: }
336:
337:
338: /*
339: ================
340: =
341: = R_DrawVisSprite
342: =
343: = mfloorclip and mceilingclip should also be set
344: ================
345: */
346:
347: void R_DrawVisSprite (vissprite_t *vis, int x1, int x2)
348: {
349: column_t *column;
350: int texturecolumn;
351: fixed_t frac;
352: patch_t *patch;
353: fixed_t baseclip;
354:
355:
356: patch = W_CacheLumpNum(vis->patch+firstspritelump, PU_CACHE);
357:
358: dc_colormap = vis->colormap;
359:
360: // if(!dc_colormap)
361: // colfunc = fuzzcolfunc; // NULL colormap = shadow draw
362:
363: if(vis->mobjflags&MF_SHADOW)
364: {
365: if(vis->mobjflags&MF_TRANSLATION)
366: {
367: colfunc = R_DrawTranslatedFuzzColumn;
368: dc_translation = translationtables - 256 +
369: ((vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8));
370: }
371: else
372: { // Draw using shadow column function
373: colfunc = fuzzcolfunc;
374: }
375: }
376: else if(vis->mobjflags&MF_TRANSLATION)
377: {
378: // Draw using translated column function
379: colfunc = R_DrawTranslatedColumn;
380: dc_translation = translationtables - 256 +
381: ( (vis->mobjflags & MF_TRANSLATION) >> (MF_TRANSSHIFT-8) );
382: }
383:
384: dc_iscale = abs(vis->xiscale)>>detailshift;
385: dc_texturemid = vis->texturemid;
386: frac = vis->startfrac;
387: spryscale = vis->scale;
388:
389: sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale);
390:
391: // check to see if weapon is a vissprite
392: if(vis->psprite)
393: {
394: dc_texturemid += FixedMul(((centery-viewheight/2)<<FRACBITS),
395: vis->xiscale);
396: sprtopscreen += (viewheight/2-centery)<<FRACBITS;
397: }
398:
399: if(vis->footclip && !vis->psprite)
400: {
401: sprbotscreen = sprtopscreen+FixedMul(patch->height<<FRACBITS,
402: spryscale);
403: baseclip = (sprbotscreen-FixedMul(vis->footclip<<FRACBITS,
404: spryscale))>>FRACBITS;
405: }
406: else
407: {
408: baseclip = -1;
409: }
410:
411: for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale)
412: {
413: texturecolumn = frac>>FRACBITS;
414: #ifdef RANGECHECK
415: if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
416: I_Error ("R_DrawSpriteRange: bad texturecolumn");
417: #endif
418: column = (column_t *) ((byte *)patch +
419: LONG(patch->columnofs[texturecolumn]));
420: R_DrawMaskedColumn (column, baseclip);
421: }
422:
423: colfunc = basecolfunc;
424: }
425:
426:
427:
428: /*
429: ===================
430: =
431: = R_ProjectSprite
432: =
433: = Generates a vissprite for a thing if it might be visible
434: =
435: ===================
436: */
437:
438: void R_ProjectSprite (mobj_t *thing)
439: {
440: fixed_t trx,try;
441: fixed_t gxt,gyt;
442: fixed_t tx,tz;
443: fixed_t xscale;
444: int x1, x2;
445: spritedef_t *sprdef;
446: spriteframe_t *sprframe;
447: int lump;
448: unsigned rot;
449: boolean flip;
450: int index;
451: vissprite_t *vis;
452: angle_t ang;
453: fixed_t iscale;
454:
455: if(thing->flags2&MF2_DONTDRAW)
456: { // Never make a vissprite when MF2_DONTDRAW is flagged.
457: return;
458: }
459:
460: //
461: // transform the origin point
462: //
463: trx = thing->x - viewx;
464: try = thing->y - viewy;
465:
466: gxt = FixedMul(trx,viewcos);
467: gyt = -FixedMul(try,viewsin);
468: tz = gxt-gyt;
469:
470: if (tz < MINZ)
471: return; // thing is behind view plane
472: xscale = FixedDiv(projection, tz);
473:
474: gxt = -FixedMul(trx,viewsin);
475: gyt = FixedMul(try,viewcos);
476: tx = -(gyt+gxt);
477:
478: if (abs(tx)>(tz<<2))
479: return; // too far off the side
480:
481: //
482: // decide which patch to use for sprite reletive to player
483: //
484: #ifdef RANGECHECK
485: if ((unsigned)thing->sprite >= numsprites)
486: I_Error ("R_ProjectSprite: invalid sprite number %i ",thing->sprite);
487: #endif
488: sprdef = &sprites[thing->sprite];
489: #ifdef RANGECHECK
490: if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes )
491: I_Error ("R_ProjectSprite: invalid sprite frame %i : %i "
492: ,thing->sprite, thing->frame);
493: #endif
494: sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK];
495:
496: if (sprframe->rotate)
497: { // choose a different rotation based on player view
498: ang = R_PointToAngle (thing->x, thing->y);
499: rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29;
500: lump = sprframe->lump[rot];
501: flip = (boolean)sprframe->flip[rot];
502: }
503: else
504: { // use single rotation for all views
505: lump = sprframe->lump[0];
506: flip = (boolean)sprframe->flip[0];
507: }
508:
509: //
510: // calculate edges of the shape
511: //
512: tx -= spriteoffset[lump];
513: x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS;
514: if (x1 > viewwidth)
515: return; // off the right side
516: tx += spritewidth[lump];
517: x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1;
518: if (x2 < 0)
519: return; // off the left side
520:
521:
522: //
523: // store information in a vissprite
524: //
525: vis = R_NewVisSprite ();
526: vis->mobjflags = thing->flags;
527: vis->psprite = false;
528: vis->scale = xscale<<detailshift;
529: vis->gx = thing->x;
530: vis->gy = thing->y;
531: vis->gz = thing->z;
532: vis->gzt = thing->z + spritetopoffset[lump];
533:
534: // foot clipping
535: if(thing->flags2&MF2_FEETARECLIPPED
536: && thing->z <= thing->subsector->sector->floorheight)
537: {
538: vis->footclip = 10;
539: }
540: else vis->footclip = 0;
541: vis->texturemid = vis->gzt - viewz - (vis->footclip<<FRACBITS);
542:
543: vis->x1 = x1 < 0 ? 0 : x1;
544: vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
545: iscale = FixedDiv (FRACUNIT, xscale);
546: if (flip)
547: {
548: vis->startfrac = spritewidth[lump]-1;
549: vis->xiscale = -iscale;
550: }
551: else
552: {
553: vis->startfrac = 0;
554: vis->xiscale = iscale;
555: }
556: if (vis->x1 > x1)
557: vis->startfrac += vis->xiscale*(vis->x1-x1);
558: vis->patch = lump;
559: //
560: // get light level
561: //
562:
563: // if (thing->flags & MF_SHADOW)
564: // vis->colormap = NULL; // shadow draw
565: // else ...
566:
567: if (fixedcolormap)
568: vis->colormap = fixedcolormap; // fixed map
569: else if (thing->frame & FF_FULLBRIGHT)
570: vis->colormap = colormaps; // full bright
571: else
572: { // diminished light
573: index = xscale>>(LIGHTSCALESHIFT-detailshift);
574: if (index >= MAXLIGHTSCALE)
575: index = MAXLIGHTSCALE-1;
576: vis->colormap = spritelights[index];
577: }
578: }
579:
580:
581:
582:
583: /*
584: ========================
585: =
586: = R_AddSprites
587: =
588: ========================
589: */
590:
591: void R_AddSprites (sector_t *sec)
592: {
593: mobj_t *thing;
594: int lightnum;
595:
596: if (sec->validcount == validcount)
597: return; // already added
598:
599: sec->validcount = validcount;
600:
601: lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight;
602: if (lightnum < 0)
603: spritelights = scalelight[0];
604: else if (lightnum >= LIGHTLEVELS)
605: spritelights = scalelight[LIGHTLEVELS-1];
606: else
607: spritelights = scalelight[lightnum];
608:
609:
610: for (thing = sec->thinglist ; thing ; thing = thing->snext)
611: R_ProjectSprite (thing);
612: }
613:
614:
615: /*
616: ========================
617: =
618: = R_DrawPSprite
619: =
620: ========================
621: */
622:
623: int PSpriteSY[NUMWEAPONS] =
624: {
625: 0, // staff
626: 5*FRACUNIT, // goldwand
627: 15*FRACUNIT, // crossbow
628: 15*FRACUNIT, // blaster
629: 15*FRACUNIT, // skullrod
630: 15*FRACUNIT, // phoenix rod
631: 15*FRACUNIT, // mace
632: 15*FRACUNIT, // gauntlets
633: 15*FRACUNIT // beak
634: };
635:
636: void R_DrawPSprite (pspdef_t *psp)
637: {
638: fixed_t tx;
639: int x1, x2;
640: spritedef_t *sprdef;
641: spriteframe_t *sprframe;
642: int lump;
643: boolean flip;
644: vissprite_t *vis, avis;
645:
646: int tempangle;
647:
648: //
649: // decide which patch to use
650: //
651: #ifdef RANGECHECK
652: if ( (unsigned)psp->state->sprite >= numsprites)
653: I_Error ("R_ProjectSprite: invalid sprite number %i "
654: , psp->state->sprite);
655: #endif
656: sprdef = &sprites[psp->state->sprite];
657: #ifdef RANGECHECK
658: if ( (psp->state->frame & FF_FRAMEMASK) >= sprdef->numframes)
659: I_Error ("R_ProjectSprite: invalid sprite frame %i : %i "
660: , psp->state->sprite, psp->state->frame);
661: #endif
662: sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ];
663:
664: lump = sprframe->lump[0];
665: flip = (boolean)sprframe->flip[0];
666:
667: //
668: // calculate edges of the shape
669: //
670: tx = psp->sx-160*FRACUNIT;
671:
672: tx -= spriteoffset[lump];
673: if(viewangleoffset)
674: {
675: tempangle = ((centerxfrac/1024)*(viewangleoffset>>ANGLETOFINESHIFT));
676: }
677: else
678: {
679: tempangle = 0;
680: }
681: x1 = (centerxfrac + FixedMul (tx,pspritescale)+tempangle ) >>FRACBITS;
682: if (x1 > viewwidth)
683: return; // off the right side
684: tx += spritewidth[lump];
685: x2 = ((centerxfrac + FixedMul (tx, pspritescale)+tempangle ) >>FRACBITS) - 1;
686: if (x2 < 0)
687: return; // off the left side
688:
689: //
690: // store information in a vissprite
691: //
692: vis = &avis;
693: vis->mobjflags = 0;
694: vis->psprite = true;
695: vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2-(psp->sy-spritetopoffset[lump]);
696: if(viewheight == SCREENHEIGHT)
697: {
698: vis->texturemid -= PSpriteSY[players[consoleplayer].readyweapon];
699: }
700: vis->x1 = x1 < 0 ? 0 : x1;
701: vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
702: vis->scale = pspritescale<<detailshift;
703: if (flip)
704: {
705: vis->xiscale = -pspriteiscale;
706: vis->startfrac = spritewidth[lump]-1;
707: }
708: else
709: {
710: vis->xiscale = pspriteiscale;
711: vis->startfrac = 0;
712: }
713: if (vis->x1 > x1)
714: vis->startfrac += vis->xiscale*(vis->x1-x1);
715: vis->patch = lump;
716:
717: if(viewplayer->powers[pw_invisibility] > 4*32 ||
718: viewplayer->powers[pw_invisibility] & 8)
719: {
720: // Invisibility
721: vis->colormap = spritelights[MAXLIGHTSCALE-1];
722: vis->mobjflags |= MF_SHADOW;
723: }
724: else if(fixedcolormap)
725: {
726: // Fixed color
727: vis->colormap = fixedcolormap;
728: }
729: else if(psp->state->frame & FF_FULLBRIGHT)
730: {
731: // Full bright
732: vis->colormap = colormaps;
733: }
734: else
735: {
736: // local light
737: vis->colormap = spritelights[MAXLIGHTSCALE-1];
738: }
739: R_DrawVisSprite(vis, vis->x1, vis->x2);
740: }
741:
742: /*
743: ========================
744: =
745: = R_DrawPlayerSprites
746: =
747: ========================
748: */
749:
750: void R_DrawPlayerSprites (void)
751: {
752: int i, lightnum;
753: pspdef_t *psp;
754:
755: //
756: // get light level
757: //
758: lightnum = (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT)
759: +extralight;
760: if (lightnum < 0)
761: spritelights = scalelight[0];
762: else if (lightnum >= LIGHTLEVELS)
763: spritelights = scalelight[LIGHTLEVELS-1];
764: else
765: spritelights = scalelight[lightnum];
766: //
767: // clip to screen bounds
768: //
769: mfloorclip = screenheightarray;
770: mceilingclip = negonearray;
771:
772: //
773: // add all active psprites
774: //
775: for (i=0, psp=viewplayer->psprites ; i<NUMPSPRITES ; i++,psp++)
776: if (psp->state)
777: R_DrawPSprite (psp);
778:
779: }
780:
781:
782: /*
783: ========================
784: =
785: = R_SortVisSprites
786: =
787: ========================
788: */
789:
790: vissprite_t vsprsortedhead;
791:
792: void R_SortVisSprites (void)
793: {
794: int i, count;
795: vissprite_t *ds, *best;
796: vissprite_t unsorted;
797: fixed_t bestscale;
798:
799: count = vissprite_p - vissprites;
800:
801: unsorted.next = unsorted.prev = &unsorted;
802: if (!count)
803: return;
804:
805: for (ds=vissprites ; ds<vissprite_p ; ds++)
806: {
807: ds->next = ds+1;
808: ds->prev = ds-1;
809: }
810: vissprites[0].prev = &unsorted;
811: unsorted.next = &vissprites[0];
812: (vissprite_p-1)->next = &unsorted;
813: unsorted.prev = vissprite_p-1;
814:
815: //
816: // pull the vissprites out by scale
817: //
818: best = 0; // shut up the compiler warning
819: vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
820: for (i=0 ; i<count ; i++)
821: {
822: bestscale = MAXINT;
823: for (ds=unsorted.next ; ds!= &unsorted ; ds=ds->next)
824: {
825: if (ds->scale < bestscale)
826: {
827: bestscale = ds->scale;
828: best = ds;
829: }
830: }
831: best->next->prev = best->prev;
832: best->prev->next = best->next;
833: best->next = &vsprsortedhead;
834: best->prev = vsprsortedhead.prev;
835: vsprsortedhead.prev->next = best;
836: vsprsortedhead.prev = best;
837: }
838: }
839:
840:
841:
842: /*
843: ========================
844: =
845: = R_DrawSprite
846: =
847: ========================
848: */
849:
850: void R_DrawSprite (vissprite_t *spr)
851: {
852: drawseg_t *ds;
853: short clipbot[SCREENWIDTH], cliptop[SCREENWIDTH];
854: int x, r1, r2;
855: fixed_t scale, lowscale;
856: int silhouette;
857:
858: for (x = spr->x1 ; x<=spr->x2 ; x++)
859: clipbot[x] = cliptop[x] = -2;
860:
861: //
862: // scan drawsegs from end to start for obscuring segs
863: // the first drawseg that has a greater scale is the clip seg
864: //
865: for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
866: {
867: //
868: // determine if the drawseg obscures the sprite
869: //
870: if (ds->x1 > spr->x2 || ds->x2 < spr->x1 ||
871: (!ds->silhouette && !ds->maskedtexturecol) )
872: continue; // doesn't cover sprite
873:
874: r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
875: r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;
876: if (ds->scale1 > ds->scale2)
877: {
878: lowscale = ds->scale2;
879: scale = ds->scale1;
880: }
881: else
882: {
883: lowscale = ds->scale1;
884: scale = ds->scale2;
885: }
886:
887: if (scale < spr->scale || ( lowscale < spr->scale
888: && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) )
889: {
890: if (ds->maskedtexturecol) // masked mid texture
891: R_RenderMaskedSegRange (ds, r1, r2);
892: continue; // seg is behind sprite
893: }
894:
895: //
896: // clip this piece of the sprite
897: //
898: silhouette = ds->silhouette;
899: if (spr->gz >= ds->bsilheight)
900: silhouette &= ~SIL_BOTTOM;
901: if (spr->gzt <= ds->tsilheight)
902: silhouette &= ~SIL_TOP;
903:
904: if (silhouette == 1)
905: { // bottom sil
906: for (x=r1 ; x<=r2 ; x++)
907: if (clipbot[x] == -2)
908: clipbot[x] = ds->sprbottomclip[x];
909: }
910: else if (silhouette == 2)
911: { // top sil
912: for (x=r1 ; x<=r2 ; x++)
913: if (cliptop[x] == -2)
914: cliptop[x] = ds->sprtopclip[x];
915: }
916: else if (silhouette == 3)
917: { // both
918: for (x=r1 ; x<=r2 ; x++)
919: {
920: if (clipbot[x] == -2)
921: clipbot[x] = ds->sprbottomclip[x];
922: if (cliptop[x] == -2)
923: cliptop[x] = ds->sprtopclip[x];
924: }
925: }
926:
927: }
928:
929: //
930: // all clipping has been performed, so draw the sprite
931: //
932:
933: // check for unclipped columns
934: for (x = spr->x1 ; x<=spr->x2 ; x++)
935: {
936: if (clipbot[x] == -2)
937: clipbot[x] = viewheight;
938: if (cliptop[x] == -2)
939: cliptop[x] = -1;
940: }
941:
942: mfloorclip = clipbot;
943: mceilingclip = cliptop;
944: R_DrawVisSprite (spr, spr->x1, spr->x2);
945: }
946:
947:
948: /*
949: ========================
950: =
951: = R_DrawMasked
952: =
953: ========================
954: */
955:
956: void R_DrawMasked (void)
957: {
958: vissprite_t *spr;
959: drawseg_t *ds;
960:
961: R_SortVisSprites ();
962:
963: if (vissprite_p > vissprites)
964: {
965: // draw all vissprites back to front
966:
967: for (spr = vsprsortedhead.next ; spr != &vsprsortedhead
968: ; spr=spr->next)
969: R_DrawSprite (spr);
970: }
971:
972: //
973: // render any remaining masked mid textures
974: //
975: for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
976: if (ds->maskedtexturecol)
977: R_RenderMaskedSegRange (ds, ds->x1, ds->x2);
978:
979: //
980: // draw the psprites on top of everything
981: //
982: // Added for the sideviewing with an external device
983: if (viewangleoffset <= 1024<<ANGLETOFINESHIFT || viewangleoffset >=
984: -1024<<ANGLETOFINESHIFT)
985: { // don't draw on side views
986: R_DrawPlayerSprites ();
987: }
988:
989: // if (!viewangleoffset) // don't draw on side views
990: // R_DrawPlayerSprites ();
991: }
992:
993:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.