Annotation of doom/p_maputl.c, revision 1.1.1.5

1.1.1.4   root        1: // Emacs style mode select   -*- C++ -*- 
                      2: //-----------------------------------------------------------------------------
                      3: //
                      4: // $Id:$
                      5: //
                      6: // Copyright (C) 1993-1996 by id Software, Inc.
                      7: //
1.1.1.5 ! root        8: // This program is free software; you can redistribute it and/or
        !             9: // modify it under the terms of the GNU General Public License
        !            10: // as published by the Free Software Foundation; either version 2
        !            11: // of the License, or (at your option) any later version.
1.1.1.4   root       12: //
1.1.1.5 ! root       13: // This program is distributed in the hope that it will be useful,
1.1.1.4   root       14: // but WITHOUT ANY WARRANTY; without even the implied warranty of
1.1.1.5 ! root       15: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            16: // GNU General Public License for more details.
1.1.1.4   root       17: //
                     18: // $Log:$
                     19: //
                     20: // DESCRIPTION:
                     21: //     Movement/collision utility functions,
                     22: //     as used by function in p_map.c. 
                     23: //     BLOCKMAP Iterator functions,
                     24: //     and some PIT_* functions to use for iteration.
                     25: //
                     26: //-----------------------------------------------------------------------------
1.1       root       27: 
1.1.1.4   root       28: static const char
                     29: rcsid[] = "$Id: p_maputl.c,v 1.5 1997/02/03 22:45:11 b1 Exp $";
1.1       root       30: 
                     31: 
1.1.1.4   root       32: #include <stdlib.h>
1.1       root       33: 
                     34: 
1.1.1.4   root       35: #include "m_bbox.h"
1.1       root       36: 
1.1.1.4   root       37: #include "doomdef.h"
                     38: #include "p_local.h"
1.1.1.3   root       39: 
                     40: 
1.1.1.4   root       41: // State.
                     42: #include "r_state.h"
1.1.1.3   root       43: 
1.1.1.4   root       44: //
                     45: // P_AproxDistance
                     46: // Gives an estimation of distance (not exact)
                     47: //
1.1.1.3   root       48: 
1.1.1.4   root       49: fixed_t
                     50: P_AproxDistance
                     51: ( fixed_t      dx,
                     52:   fixed_t      dy )
                     53: {
                     54:     dx = abs(dx);
                     55:     dy = abs(dy);
                     56:     if (dx < dy)
                     57:        return dx+dy-(dx>>1);
                     58:     return dx+dy-(dy>>1);
1.1       root       59: }
                     60: 
                     61: 
1.1.1.4   root       62: //
                     63: // P_PointOnLineSide
                     64: // Returns 0 or 1
                     65: //
                     66: int
                     67: P_PointOnLineSide
                     68: ( fixed_t      x,
                     69:   fixed_t      y,
                     70:   line_t*      line )
1.1.1.2   root       71: {
1.1.1.4   root       72:     fixed_t    dx;
                     73:     fixed_t    dy;
                     74:     fixed_t    left;
                     75:     fixed_t    right;
                     76:        
                     77:     if (!line->dx)
                     78:     {
                     79:        if (x <= line->v1->x)
                     80:            return line->dy > 0;
                     81:        
                     82:        return line->dy < 0;
                     83:     }
                     84:     if (!line->dy)
                     85:     {
                     86:        if (y <= line->v1->y)
                     87:            return line->dx < 0;
                     88:        
                     89:        return line->dx > 0;
                     90:     }
                     91:        
                     92:     dx = (x - line->v1->x);
                     93:     dy = (y - line->v1->y);
                     94:        
                     95:     left = FixedMul ( line->dy>>FRACBITS , dx );
                     96:     right = FixedMul ( dy , line->dx>>FRACBITS );
                     97:        
                     98:     if (right < left)
                     99:        return 0;               // front side
                    100:     return 1;                  // back side
1.1.1.2   root      101: }
                    102: 
1.1       root      103: 
1.1.1.3   root      104: 
1.1.1.4   root      105: //
                    106: // P_BoxOnLineSide
                    107: // Considers the line to be infinite
                    108: // Returns side 0 or 1, -1 if box crosses the line.
                    109: //
                    110: int
                    111: P_BoxOnLineSide
                    112: ( fixed_t*     tmbox,
                    113:   line_t*      ld )
                    114: {
                    115:     int                p1;
                    116:     int                p2;
                    117:        
                    118:     switch (ld->slopetype)
                    119:     {
                    120:       case ST_HORIZONTAL:
                    121:        p1 = tmbox[BOXTOP] > ld->v1->y;
                    122:        p2 = tmbox[BOXBOTTOM] > ld->v1->y;
                    123:        if (ld->dx < 0)
1.1       root      124:        {
1.1.1.4   root      125:            p1 ^= 1;
                    126:            p2 ^= 1;
1.1       root      127:        }
1.1.1.4   root      128:        break;
                    129:        
                    130:       case ST_VERTICAL:
                    131:        p1 = tmbox[BOXRIGHT] < ld->v1->x;
                    132:        p2 = tmbox[BOXLEFT] < ld->v1->x;
                    133:        if (ld->dy < 0)
1.1       root      134:        {
1.1.1.4   root      135:            p1 ^= 1;
                    136:            p2 ^= 1;
1.1       root      137:        }
1.1.1.4   root      138:        break;
                    139:        
                    140:       case ST_POSITIVE:
                    141:        p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld);
                    142:        p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld);
                    143:        break;
                    144:        
                    145:       case ST_NEGATIVE:
                    146:        p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld);
                    147:        p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld);
                    148:        break;
                    149:     }
1.1.1.3   root      150: 
1.1.1.4   root      151:     if (p1 == p2)
                    152:        return p1;
                    153:     return -1;
                    154: }
1.1.1.3   root      155: 
                    156: 
1.1.1.4   root      157: //
                    158: // P_PointOnDivlineSide
                    159: // Returns 0 or 1.
                    160: //
                    161: int
                    162: P_PointOnDivlineSide
                    163: ( fixed_t      x,
                    164:   fixed_t      y,
                    165:   divline_t*   line )
                    166: {
                    167:     fixed_t    dx;
                    168:     fixed_t    dy;
                    169:     fixed_t    left;
                    170:     fixed_t    right;
                    171:        
                    172:     if (!line->dx)
                    173:     {
                    174:        if (x <= line->x)
                    175:            return line->dy > 0;
                    176:        
                    177:        return line->dy < 0;
                    178:     }
                    179:     if (!line->dy)
                    180:     {
                    181:        if (y <= line->y)
                    182:            return line->dx < 0;
1.1.1.3   root      183: 
1.1.1.4   root      184:        return line->dx > 0;
                    185:     }
                    186:        
                    187:     dx = (x - line->x);
                    188:     dy = (y - line->y);
                    189:        
                    190:     // try to quickly decide by looking at sign bits
                    191:     if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 )
                    192:     {
                    193:        if ( (line->dy ^ dx) & 0x80000000 )
                    194:            return 1;           // (left is negative)
                    195:        return 0;
                    196:     }
                    197:        
                    198:     left = FixedMul ( line->dy>>8, dx>>8 );
                    199:     right = FixedMul ( dy>>8 , line->dx>>8 );
                    200:        
                    201:     if (right < left)
                    202:        return 0;               // front side
                    203:     return 1;                  // back side
1.1       root      204: }
                    205: 
                    206: 
                    207: 
1.1.1.4   root      208: //
                    209: // P_MakeDivline
                    210: //
                    211: void
                    212: P_MakeDivline
                    213: ( line_t*      li,
                    214:   divline_t*   dl )
1.1       root      215: {
1.1.1.4   root      216:     dl->x = li->v1->x;
                    217:     dl->y = li->v1->y;
                    218:     dl->dx = li->dx;
                    219:     dl->dy = li->dy;
1.1       root      220: }
                    221: 
                    222: 
1.1.1.2   root      223: 
1.1.1.4   root      224: //
                    225: // P_InterceptVector
                    226: // Returns the fractional intercept point
                    227: // along the first divline.
                    228: // This is only called by the addthings
                    229: // and addlines traversers.
                    230: //
                    231: fixed_t
                    232: P_InterceptVector
                    233: ( divline_t*   v2,
                    234:   divline_t*   v1 )
1.1.1.2   root      235: {
                    236: #if 1
1.1.1.4   root      237:     fixed_t    frac;
                    238:     fixed_t    num;
                    239:     fixed_t    den;
                    240:        
                    241:     den = FixedMul (v1->dy>>8,v2->dx) - FixedMul(v1->dx>>8,v2->dy);
                    242: 
                    243:     if (den == 0)
                    244:        return 0;
                    245:     // I_Error ("P_InterceptVector: parallel");
                    246:     
                    247:     num =
                    248:        FixedMul ( (v1->x - v2->x)>>8 ,v1->dy )
                    249:        +FixedMul ( (v2->y - v1->y)>>8, v1->dx );
                    250: 
                    251:     frac = FixedDiv (num , den);
                    252: 
                    253:     return frac;
                    254: #else  // UNUSED, float debug.
                    255:     float      frac;
                    256:     float      num;
                    257:     float      den;
                    258:     float      v1x;
                    259:     float      v1y;
                    260:     float      v1dx;
                    261:     float      v1dy;
                    262:     float      v2x;
                    263:     float      v2y;
                    264:     float      v2dx;
                    265:     float      v2dy;
                    266: 
                    267:     v1x = (float)v1->x/FRACUNIT;
                    268:     v1y = (float)v1->y/FRACUNIT;
                    269:     v1dx = (float)v1->dx/FRACUNIT;
                    270:     v1dy = (float)v1->dy/FRACUNIT;
                    271:     v2x = (float)v2->x/FRACUNIT;
                    272:     v2y = (float)v2->y/FRACUNIT;
                    273:     v2dx = (float)v2->dx/FRACUNIT;
                    274:     v2dy = (float)v2->dy/FRACUNIT;
                    275:        
                    276:     den = v1dy*v2dx - v1dx*v2dy;
1.1.1.3   root      277: 
1.1.1.4   root      278:     if (den == 0)
                    279:        return 0;       // parallel
                    280:     
                    281:     num = (v1x - v2x)*v1dy + (v2y - v1y)*v1dx;
                    282:     frac = num / den;
1.1.1.2   root      283: 
1.1.1.4   root      284:     return frac*FRACUNIT;
1.1.1.2   root      285: #endif
                    286: }
                    287: 
1.1       root      288: 
1.1.1.4   root      289: //
                    290: // P_LineOpening
                    291: // Sets opentop and openbottom to the window
                    292: // through a two sided line.
                    293: // OPTIMIZE: keep this precalculated
                    294: //
                    295: fixed_t opentop;
                    296: fixed_t openbottom;
                    297: fixed_t openrange;
                    298: fixed_t        lowfloor;
                    299: 
1.1       root      300: 
1.1.1.4   root      301: void P_LineOpening (line_t* linedef)
1.1       root      302: {
1.1.1.4   root      303:     sector_t*  front;
                    304:     sector_t*  back;
                    305:        
                    306:     if (linedef->sidenum[1] == -1)
                    307:     {
                    308:        // single sided line
                    309:        openrange = 0;
                    310:        return;
                    311:     }
                    312:         
                    313:     front = linedef->frontsector;
                    314:     back = linedef->backsector;
                    315:        
                    316:     if (front->ceilingheight < back->ceilingheight)
                    317:        opentop = front->ceilingheight;
                    318:     else
                    319:        opentop = back->ceilingheight;
                    320: 
                    321:     if (front->floorheight > back->floorheight)
                    322:     {
                    323:        openbottom = front->floorheight;
                    324:        lowfloor = back->floorheight;
                    325:     }
                    326:     else
                    327:     {
                    328:        openbottom = back->floorheight;
                    329:        lowfloor = front->floorheight;
                    330:     }
                    331:        
                    332:     openrange = opentop - openbottom;
                    333: }
1.1.1.3   root      334: 
                    335: 
1.1.1.4   root      336: //
                    337: // THING POSITION SETTING
                    338: //
                    339: 
                    340: 
                    341: //
                    342: // P_UnsetThingPosition
                    343: // Unlinks a thing from block map and sectors.
                    344: // On each position change, BLOCKMAP and other
                    345: // lookups maintaining lists ot things inside
                    346: // these structures need to be updated.
                    347: //
                    348: void P_UnsetThingPosition (mobj_t* thing)
                    349: {
                    350:     int                blockx;
                    351:     int                blocky;
                    352: 
                    353:     if ( ! (thing->flags & MF_NOSECTOR) )
                    354:     {
                    355:        // inert things don't need to be in blockmap?
                    356:        // unlink from subsector
                    357:        if (thing->snext)
                    358:            thing->snext->sprev = thing->sprev;
1.1.1.3   root      359: 
1.1.1.4   root      360:        if (thing->sprev)
                    361:            thing->sprev->snext = thing->snext;
1.1       root      362:        else
1.1.1.4   root      363:            thing->subsector->sector->thinglist = thing->snext;
                    364:     }
                    365:        
                    366:     if ( ! (thing->flags & MF_NOBLOCKMAP) )
                    367:     {
                    368:        // inert things don't need to be in blockmap
                    369:        // unlink from block map
                    370:        if (thing->bnext)
                    371:            thing->bnext->bprev = thing->bprev;
                    372:        
                    373:        if (thing->bprev)
                    374:            thing->bprev->bnext = thing->bnext;
1.1       root      375:        else
                    376:        {
1.1.1.4   root      377:            blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
                    378:            blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
1.1.1.3   root      379: 
1.1.1.4   root      380:            if (blockx>=0 && blockx < bmapwidth
                    381:                && blocky>=0 && blocky <bmapheight)
                    382:            {
                    383:                blocklinks[blocky*bmapwidth+blockx] = thing->bnext;
                    384:            }
                    385:        }
                    386:     }
1.1       root      387: }
                    388: 
                    389: 
1.1.1.4   root      390: //
                    391: // P_SetThingPosition
                    392: // Links a thing into both a block and a subsector
                    393: // based on it's x y.
                    394: // Sets thing->subsector properly
                    395: //
                    396: void
                    397: P_SetThingPosition (mobj_t* thing)
                    398: {
                    399:     subsector_t*       ss;
                    400:     sector_t*          sec;
                    401:     int                        blockx;
                    402:     int                        blocky;
                    403:     mobj_t**           link;
                    404: 
                    405:     
                    406:     // link into subsector
                    407:     ss = R_PointInSubsector (thing->x,thing->y);
                    408:     thing->subsector = ss;
                    409:     
                    410:     if ( ! (thing->flags & MF_NOSECTOR) )
                    411:     {
                    412:        // invisible things don't go into the sector links
                    413:        sec = ss->sector;
                    414:        
                    415:        thing->sprev = NULL;
                    416:        thing->snext = sec->thinglist;
1.1       root      417: 
1.1.1.4   root      418:        if (sec->thinglist)
                    419:            sec->thinglist->sprev = thing;
1.1       root      420: 
1.1.1.4   root      421:        sec->thinglist = thing;
                    422:     }
1.1       root      423: 
1.1.1.4   root      424:     
                    425:     // link into blockmap
                    426:     if ( ! (thing->flags & MF_NOBLOCKMAP) )
                    427:     {
                    428:        // inert things don't need to be in blockmap            
                    429:        blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT;
                    430:        blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT;
                    431: 
                    432:        if (blockx>=0
                    433:            && blockx < bmapwidth
                    434:            && blocky>=0
                    435:            && blocky < bmapheight)
                    436:        {
                    437:            link = &blocklinks[blocky*bmapwidth+blockx];
                    438:            thing->bprev = NULL;
                    439:            thing->bnext = *link;
                    440:            if (*link)
                    441:                (*link)->bprev = thing;
1.1       root      442: 
1.1.1.4   root      443:            *link = thing;
1.1       root      444:        }
1.1.1.4   root      445:        else
                    446:        {
                    447:            // thing is off the map
                    448:            thing->bnext = thing->bprev = NULL;
1.1       root      449:        }
1.1.1.4   root      450:     }
1.1       root      451: }
                    452: 
                    453: 
1.1.1.3   root      454: 
1.1.1.2   root      455: //
1.1.1.4   root      456: // BLOCK MAP ITERATORS
                    457: // For each line/thing in the given mapblock,
                    458: // call the passed PIT_* function.
                    459: // If the function returns false,
                    460: // exit with false without checking anything else.
1.1.1.2   root      461: //
1.1       root      462: 
                    463: 
1.1.1.4   root      464: //
                    465: // P_BlockLinesIterator
                    466: // The validcount flags are used to avoid checking lines
                    467: // that are marked in multiple mapblocks,
                    468: // so increment validcount before the first call
                    469: // to P_BlockLinesIterator, then make one or more calls
                    470: // to it.
                    471: //
                    472: boolean
                    473: P_BlockLinesIterator
                    474: ( int                  x,
                    475:   int                  y,
                    476:   boolean(*func)(line_t*) )
1.1       root      477: {
1.1.1.4   root      478:     int                        offset;
                    479:     short*             list;
                    480:     line_t*            ld;
                    481:        
                    482:     if (x<0
                    483:        || y<0
                    484:        || x>=bmapwidth
                    485:        || y>=bmapheight)
                    486:     {
                    487:        return true;
                    488:     }
                    489:     
                    490:     offset = y*bmapwidth+x;
                    491:        
                    492:     offset = *(blockmap+offset);
1.1       root      493: 
1.1.1.4   root      494:     for ( list = blockmaplump+offset ; *list != -1 ; list++)
                    495:     {
                    496:        ld = &lines[*list];
1.1.1.3   root      497: 
1.1.1.4   root      498:        if (ld->validcount == validcount)
                    499:            continue;   // line has already been checked
1.1.1.3   root      500: 
1.1.1.4   root      501:        ld->validcount = validcount;
                    502:                
                    503:        if ( !func(ld) )
                    504:            return false;
                    505:     }
                    506:     return true;       // everything was checked
1.1       root      507: }
                    508: 
                    509: 
1.1.1.4   root      510: //
                    511: // P_BlockThingsIterator
                    512: //
                    513: boolean
                    514: P_BlockThingsIterator
                    515: ( int                  x,
                    516:   int                  y,
                    517:   boolean(*func)(mobj_t*) )
1.1       root      518: {
1.1.1.4   root      519:     mobj_t*            mobj;
                    520:        
                    521:     if ( x<0
                    522:         || y<0
                    523:         || x>=bmapwidth
                    524:         || y>=bmapheight)
                    525:     {
1.1       root      526:        return true;
1.1.1.4   root      527:     }
                    528:     
                    529: 
                    530:     for (mobj = blocklinks[y*bmapwidth+x] ;
                    531:         mobj ;
                    532:         mobj = mobj->bnext)
                    533:     {
                    534:        if (!func( mobj ) )
                    535:            return false;
                    536:     }
                    537:     return true;
1.1       root      538: }
                    539: 
1.1.1.2   root      540: 
                    541: 
1.1.1.4   root      542: //
                    543: // INTERCEPT ROUTINES
                    544: //
                    545: intercept_t    intercepts[MAXINTERCEPTS];
                    546: intercept_t*   intercept_p;
1.1.1.2   root      547: 
1.1.1.4   root      548: divline_t      trace;
                    549: boolean        earlyout;
                    550: int            ptflags;
1.1.1.2   root      551: 
                    552: //
1.1.1.4   root      553: // PIT_AddLineIntercepts.
                    554: // Looks for lines in the given block
                    555: // that intercept the given trace
                    556: // to add to the intercepts list.
1.1.1.2   root      557: //
1.1.1.4   root      558: // A line is crossed if its endpoints
                    559: // are on opposite sides of the trace.
                    560: // Returns true if earlyout and a solid line hit.
                    561: //
                    562: boolean
                    563: PIT_AddLineIntercepts (line_t* ld)
                    564: {
                    565:     int                        s1;
                    566:     int                        s2;
                    567:     fixed_t            frac;
                    568:     divline_t          dl;
                    569:        
                    570:     // avoid precision problems with two routines
                    571:     if ( trace.dx > FRACUNIT*16
                    572:         || trace.dy > FRACUNIT*16
                    573:         || trace.dx < -FRACUNIT*16
                    574:         || trace.dy < -FRACUNIT*16)
                    575:     {
                    576:        s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace);
                    577:        s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace);
                    578:     }
                    579:     else
                    580:     {
                    581:        s1 = P_PointOnLineSide (trace.x, trace.y, ld);
                    582:        s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld);
                    583:     }
                    584:     
                    585:     if (s1 == s2)
                    586:        return true;    // line isn't crossed
                    587:     
                    588:     // hit the line
                    589:     P_MakeDivline (ld, &dl);
                    590:     frac = P_InterceptVector (&trace, &dl);
1.1.1.3   root      591: 
1.1.1.4   root      592:     if (frac < 0)
                    593:        return true;    // behind source
                    594:        
                    595:     // try to early out the check
                    596:     if (earlyout
                    597:        && frac < FRACUNIT
                    598:        && !ld->backsector)
                    599:     {
                    600:        return false;   // stop checking
                    601:     }
                    602:     
                    603:        
                    604:     intercept_p->frac = frac;
                    605:     intercept_p->isaline = true;
                    606:     intercept_p->d.line = ld;
                    607:     intercept_p++;
1.1.1.2   root      608: 
1.1.1.4   root      609:     return true;       // continue
1.1.1.2   root      610: }
                    611: 
                    612: 
                    613: 
1.1.1.4   root      614: //
                    615: // PIT_AddThingIntercepts
                    616: //
                    617: boolean PIT_AddThingIntercepts (mobj_t* thing)
1.1.1.2   root      618: {
1.1.1.4   root      619:     fixed_t            x1;
                    620:     fixed_t            y1;
                    621:     fixed_t            x2;
                    622:     fixed_t            y2;
                    623:     
                    624:     int                        s1;
                    625:     int                        s2;
                    626:     
                    627:     boolean            tracepositive;
1.1.1.3   root      628: 
1.1.1.4   root      629:     divline_t          dl;
                    630:     
                    631:     fixed_t            frac;
                    632:        
                    633:     tracepositive = (trace.dx ^ trace.dy)>0;
                    634:                
                    635:     // check a corner to corner crossection for hit
                    636:     if (tracepositive)
                    637:     {
                    638:        x1 = thing->x - thing->radius;
                    639:        y1 = thing->y + thing->radius;
                    640:                
                    641:        x2 = thing->x + thing->radius;
                    642:        y2 = thing->y - thing->radius;                  
                    643:     }
                    644:     else
                    645:     {
                    646:        x1 = thing->x - thing->radius;
                    647:        y1 = thing->y - thing->radius;
                    648:                
                    649:        x2 = thing->x + thing->radius;
                    650:        y2 = thing->y + thing->radius;                  
                    651:     }
                    652:     
                    653:     s1 = P_PointOnDivlineSide (x1, y1, &trace);
                    654:     s2 = P_PointOnDivlineSide (x2, y2, &trace);
1.1.1.2   root      655: 
1.1.1.4   root      656:     if (s1 == s2)
                    657:        return true;            // line isn't crossed
                    658:        
                    659:     dl.x = x1;
                    660:     dl.y = y1;
                    661:     dl.dx = x2-x1;
                    662:     dl.dy = y2-y1;
                    663:     
                    664:     frac = P_InterceptVector (&trace, &dl);
                    665: 
                    666:     if (frac < 0)
                    667:        return true;            // behind source
                    668: 
                    669:     intercept_p->frac = frac;
                    670:     intercept_p->isaline = false;
                    671:     intercept_p->d.thing = thing;
                    672:     intercept_p++;
                    673: 
                    674:     return true;               // keep going
1.1.1.2   root      675: }
                    676: 
                    677: 
1.1.1.4   root      678: //
                    679: // P_TraverseIntercepts
                    680: // Returns true if the traverser function returns true
                    681: // for all lines.
                    682: // 
                    683: boolean
                    684: P_TraverseIntercepts
                    685: ( traverser_t  func,
                    686:   fixed_t      maxfrac )
                    687: {
                    688:     int                        count;
                    689:     fixed_t            dist;
                    690:     intercept_t*       scan;
                    691:     intercept_t*       in;
                    692:        
                    693:     count = intercept_p - intercepts;
                    694:     
                    695:     in = 0;                    // shut up compiler warning
                    696:        
                    697:     while (count--)
                    698:     {
                    699:        dist = MAXINT;
                    700:        for (scan = intercepts ; scan<intercept_p ; scan++)
                    701:        {
                    702:            if (scan->frac < dist)
                    703:            {
                    704:                dist = scan->frac;
                    705:                in = scan;
                    706:            }
                    707:        }
                    708:        
                    709:        if (dist > maxfrac)
                    710:            return true;        // checked everything in range          
1.1.1.3   root      711: 
1.1.1.4   root      712: #if 0  // UNUSED
                    713:     {
                    714:        // don't check these yet, there may be others inserted
                    715:        in = scan = intercepts;
                    716:        for ( scan = intercepts ; scan<intercept_p ; scan++)
                    717:            if (scan->frac > maxfrac)
                    718:                *in++ = *scan;
                    719:        intercept_p = in;
                    720:        return false;
                    721:     }
1.1.1.2   root      722: #endif
                    723: 
1.1.1.4   root      724:         if ( !func (in) )
                    725:            return false;       // don't bother going farther
1.1.1.3   root      726: 
1.1.1.4   root      727:        in->frac = MAXINT;
                    728:     }
                    729:        
                    730:     return true;               // everything was traversed
1.1.1.2   root      731: }
                    732: 
                    733: 
                    734: 
                    735: 
1.1.1.4   root      736: //
                    737: // P_PathTraverse
                    738: // Traces a line from x1,y1 to x2,y2,
                    739: // calling the traverser function for each.
                    740: // Returns true if the traverser function returns true
                    741: // for all lines.
                    742: //
                    743: boolean
                    744: P_PathTraverse
                    745: ( fixed_t              x1,
                    746:   fixed_t              y1,
                    747:   fixed_t              x2,
                    748:   fixed_t              y2,
                    749:   int                  flags,
                    750:   boolean (*trav) (intercept_t *))
                    751: {
                    752:     fixed_t    xt1;
                    753:     fixed_t    yt1;
                    754:     fixed_t    xt2;
                    755:     fixed_t    yt2;
                    756:     
                    757:     fixed_t    xstep;
                    758:     fixed_t    ystep;
                    759:     
                    760:     fixed_t    partial;
                    761:     
                    762:     fixed_t    xintercept;
                    763:     fixed_t    yintercept;
                    764:     
                    765:     int                mapx;
                    766:     int                mapy;
                    767:     
                    768:     int                mapxstep;
                    769:     int                mapystep;
1.1.1.2   root      770: 
1.1.1.4   root      771:     int                count;
                    772:                
                    773:     earlyout = flags & PT_EARLYOUT;
                    774:                
                    775:     validcount++;
                    776:     intercept_p = intercepts;
                    777:        
                    778:     if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
                    779:        x1 += FRACUNIT; // don't side exactly on a line
                    780:     
                    781:     if ( ((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0)
                    782:        y1 += FRACUNIT; // don't side exactly on a line
                    783: 
                    784:     trace.x = x1;
                    785:     trace.y = y1;
                    786:     trace.dx = x2 - x1;
                    787:     trace.dy = y2 - y1;
                    788: 
                    789:     x1 -= bmaporgx;
                    790:     y1 -= bmaporgy;
                    791:     xt1 = x1>>MAPBLOCKSHIFT;
                    792:     yt1 = y1>>MAPBLOCKSHIFT;
                    793: 
                    794:     x2 -= bmaporgx;
                    795:     y2 -= bmaporgy;
                    796:     xt2 = x2>>MAPBLOCKSHIFT;
                    797:     yt2 = y2>>MAPBLOCKSHIFT;
                    798: 
                    799:     if (xt2 > xt1)
                    800:     {
                    801:        mapxstep = 1;
                    802:        partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1));
                    803:        ystep = FixedDiv (y2-y1,abs(x2-x1));
                    804:     }
                    805:     else if (xt2 < xt1)
                    806:     {
                    807:        mapxstep = -1;
                    808:        partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1);
                    809:        ystep = FixedDiv (y2-y1,abs(x2-x1));
                    810:     }
                    811:     else
                    812:     {
                    813:        mapxstep = 0;
                    814:        partial = FRACUNIT;
                    815:        ystep = 256*FRACUNIT;
                    816:     }  
1.1.1.2   root      817: 
1.1.1.4   root      818:     yintercept = (y1>>MAPBTOFRAC) + FixedMul (partial, ystep);
1.1.1.3   root      819: 
1.1.1.4   root      820:        
                    821:     if (yt2 > yt1)
                    822:     {
                    823:        mapystep = 1;
                    824:        partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1));
                    825:        xstep = FixedDiv (x2-x1,abs(y2-y1));
                    826:     }
                    827:     else if (yt2 < yt1)
                    828:     {
                    829:        mapystep = -1;
                    830:        partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1);
                    831:        xstep = FixedDiv (x2-x1,abs(y2-y1));
                    832:     }
                    833:     else
                    834:     {
                    835:        mapystep = 0;
                    836:        partial = FRACUNIT;
                    837:        xstep = 256*FRACUNIT;
                    838:     }  
                    839:     xintercept = (x1>>MAPBTOFRAC) + FixedMul (partial, xstep);
                    840:     
                    841:     // Step through map blocks.
                    842:     // Count is present to prevent a round off error
                    843:     // from skipping the break.
                    844:     mapx = xt1;
                    845:     mapy = yt1;
                    846:        
                    847:     for (count = 0 ; count < 64 ; count++)
                    848:     {
                    849:        if (flags & PT_ADDLINES)
1.1.1.2   root      850:        {
1.1.1.4   root      851:            if (!P_BlockLinesIterator (mapx, mapy,PIT_AddLineIntercepts))
                    852:                return false;   // early out
1.1.1.2   root      853:        }
                    854:        
1.1.1.4   root      855:        if (flags & PT_ADDTHINGS)
1.1.1.2   root      856:        {
1.1.1.4   root      857:            if (!P_BlockThingsIterator (mapx, mapy,PIT_AddThingIntercepts))
                    858:                return false;   // early out
                    859:        }
1.1.1.2   root      860:                
1.1.1.4   root      861:        if (mapx == xt2
                    862:            && mapy == yt2)
                    863:        {
                    864:            break;
1.1.1.2   root      865:        }
1.1.1.3   root      866:        
1.1.1.4   root      867:        if ( (yintercept >> FRACBITS) == mapy)
1.1.1.3   root      868:        {
1.1.1.4   root      869:            yintercept += ystep;
                    870:            mapx += mapxstep;
1.1.1.3   root      871:        }
1.1.1.4   root      872:        else if ( (xintercept >> FRACBITS) == mapx)
1.1.1.3   root      873:        {
1.1.1.4   root      874:            xintercept += xstep;
                    875:            mapy += mapystep;
1.1.1.3   root      876:        }
1.1.1.4   root      877:                
                    878:     }
                    879:     // go through the sorted list
                    880:     return P_TraverseIntercepts ( trav, FRACUNIT );
1.1.1.3   root      881: }
                    882: 
                    883: 
                    884: 

unix.superglobalmegacorp.com

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