Subversion Repositories Kolibri OS

Rev

Rev 298 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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