Annotation of doom/r_things.c, revision 1.1.1.3

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.