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