Annotation of doom/p_maputl.c, revision 1.1.1.4

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

unix.superglobalmegacorp.com

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