Annotation of quake1/world.c, revision 1.1.1.1

1.1       root        1: // world.c -- world query functions
                      2: 
                      3: #include "quakedef.h"
                      4: 
                      5: /*
                      6: 
                      7: entities never clip against themselves, or their owner
                      8: 
                      9: line of sight checks trace->crosscontent, but bullets don't
                     10: 
                     11: */
                     12: 
                     13: 
                     14: typedef struct
                     15: {
                     16:        vec3_t          boxmins, boxmaxs;// enclose the test object along entire move
                     17:        float           *mins, *maxs;   // size of the moving object
                     18:        vec3_t          mins2, maxs2;   // size when clipping against mosnters
                     19:        float           *start, *end;
                     20:        trace_t         trace;
                     21:        int                     type;
                     22:        edict_t         *passedict;
                     23: } moveclip_t;
                     24: 
                     25: 
                     26: int SV_HullPointContents (hull_t *hull, int num, vec3_t p);
                     27: 
                     28: /*
                     29: ===============================================================================
                     30: 
                     31: HULL BOXES
                     32: 
                     33: ===============================================================================
                     34: */
                     35: 
                     36: 
                     37: static hull_t          box_hull;
                     38: static dclipnode_t     box_clipnodes[6];
                     39: static mplane_t        box_planes[6];
                     40: 
                     41: /*
                     42: ===================
                     43: SV_InitBoxHull
                     44: 
                     45: Set up the planes and clipnodes so that the six floats of a bounding box
                     46: can just be stored out and get a proper hull_t structure.
                     47: ===================
                     48: */
                     49: void SV_InitBoxHull (void)
                     50: {
                     51:        int             i;
                     52:        int             side;
                     53: 
                     54:        box_hull.clipnodes = box_clipnodes;
                     55:        box_hull.planes = box_planes;
                     56:        box_hull.firstclipnode = 0;
                     57:        box_hull.lastclipnode = 5;
                     58: 
                     59:        for (i=0 ; i<6 ; i++)
                     60:        {
                     61:                box_clipnodes[i].planenum = i;
                     62:                
                     63:                side = i&1;
                     64:                
                     65:                box_clipnodes[i].children[side] = CONTENTS_EMPTY;
                     66:                if (i != 5)
                     67:                        box_clipnodes[i].children[side^1] = i + 1;
                     68:                else
                     69:                        box_clipnodes[i].children[side^1] = CONTENTS_SOLID;
                     70:                
                     71:                box_planes[i].type = i>>1;
                     72:                box_planes[i].normal[i>>1] = 1;
                     73:        }
                     74:        
                     75: }
                     76: 
                     77: 
                     78: /*
                     79: ===================
                     80: SV_HullForBox
                     81: 
                     82: To keep everything totally uniform, bounding boxes are turned into small
                     83: BSP trees instead of being compared directly.
                     84: ===================
                     85: */
                     86: hull_t *SV_HullForBox (vec3_t mins, vec3_t maxs)
                     87: {
                     88:        box_planes[0].dist = maxs[0];
                     89:        box_planes[1].dist = mins[0];
                     90:        box_planes[2].dist = maxs[1];
                     91:        box_planes[3].dist = mins[1];
                     92:        box_planes[4].dist = maxs[2];
                     93:        box_planes[5].dist = mins[2];
                     94: 
                     95:        return &box_hull;
                     96: }
                     97: 
                     98: 
                     99: 
                    100: /*
                    101: ================
                    102: SV_HullForEntity
                    103: 
                    104: Returns a hull that can be used for testing or clipping an object of mins/maxs
                    105: size.
                    106: Offset is filled in to contain the adjustment that must be added to the
                    107: testing object's origin to get a point to use with the returned hull.
                    108: ================
                    109: */
                    110: hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset)
                    111: {
                    112:        model_t         *model;
                    113:        vec3_t          size;
                    114:        vec3_t          hullmins, hullmaxs;
                    115:        hull_t          *hull;
                    116: 
                    117: // decide which clipping hull to use, based on the size
                    118:        if (ent->v.solid == SOLID_BSP)
                    119:        {       // explicit hulls in the BSP model
                    120:                if (ent->v.movetype != MOVETYPE_PUSH)
                    121:                        Sys_Error ("SOLID_BSP without MOVETYPE_PUSH");
                    122: 
                    123:                model = sv.models[ (int)ent->v.modelindex ];
                    124: 
                    125:                if (!model || model->type != mod_brush)
                    126:                        Sys_Error ("MOVETYPE_PUSH with a non bsp model");
                    127: 
                    128:                VectorSubtract (maxs, mins, size);
                    129:                if (size[0] < 3)
                    130:                        hull = &model->hulls[0];
                    131:                else if (size[0] <= 32)
                    132:                        hull = &model->hulls[1];
                    133:                else
                    134:                        hull = &model->hulls[2];
                    135: 
                    136: // calculate an offset value to center the origin
                    137:                VectorSubtract (hull->clip_mins, mins, offset);
                    138:                VectorAdd (offset, ent->v.origin, offset);
                    139:        }
                    140:        else
                    141:        {       // create a temp hull from bounding box sizes
                    142: 
                    143:                VectorSubtract (ent->v.mins, maxs, hullmins);
                    144:                VectorSubtract (ent->v.maxs, mins, hullmaxs);
                    145:                hull = SV_HullForBox (hullmins, hullmaxs);
                    146:                
                    147:                VectorCopy (ent->v.origin, offset);
                    148:        }
                    149: 
                    150: 
                    151:        return hull;
                    152: }
                    153: 
                    154: /*
                    155: ===============================================================================
                    156: 
                    157: ENTITY AREA CHECKING
                    158: 
                    159: ===============================================================================
                    160: */
                    161: 
                    162: typedef struct areanode_s
                    163: {
                    164:        int             axis;           // -1 = leaf node
                    165:        float   dist;
                    166:        struct areanode_s       *children[2];
                    167:        link_t  trigger_edicts;
                    168:        link_t  solid_edicts;
                    169: } areanode_t;
                    170: 
                    171: #define        AREA_DEPTH      4
                    172: #define        AREA_NODES      32
                    173: 
                    174: static areanode_t      sv_areanodes[AREA_NODES];
                    175: static int                     sv_numareanodes;
                    176: 
                    177: /*
                    178: ===============
                    179: SV_CreateAreaNode
                    180: 
                    181: ===============
                    182: */
                    183: areanode_t *SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs)
                    184: {
                    185:        areanode_t      *anode;
                    186:        vec3_t          size;
                    187:        vec3_t          mins1, maxs1, mins2, maxs2;
                    188: 
                    189:        anode = &sv_areanodes[sv_numareanodes];
                    190:        sv_numareanodes++;
                    191: 
                    192:        ClearLink (&anode->trigger_edicts);
                    193:        ClearLink (&anode->solid_edicts);
                    194:        
                    195:        if (depth == AREA_DEPTH)
                    196:        {
                    197:                anode->axis = -1;
                    198:                anode->children[0] = anode->children[1] = NULL;
                    199:                return anode;
                    200:        }
                    201:        
                    202:        VectorSubtract (maxs, mins, size);
                    203:        if (size[0] > size[1])
                    204:                anode->axis = 0;
                    205:        else
                    206:                anode->axis = 1;
                    207:        
                    208:        anode->dist = 0.5 * (maxs[anode->axis] + mins[anode->axis]);
                    209:        VectorCopy (mins, mins1);       
                    210:        VectorCopy (mins, mins2);       
                    211:        VectorCopy (maxs, maxs1);       
                    212:        VectorCopy (maxs, maxs2);       
                    213:        
                    214:        maxs1[anode->axis] = mins2[anode->axis] = anode->dist;
                    215:        
                    216:        anode->children[0] = SV_CreateAreaNode (depth+1, mins2, maxs2);
                    217:        anode->children[1] = SV_CreateAreaNode (depth+1, mins1, maxs1);
                    218: 
                    219:        return anode;
                    220: }
                    221: 
                    222: /*
                    223: ===============
                    224: SV_ClearWorld
                    225: 
                    226: ===============
                    227: */
                    228: void SV_ClearWorld (void)
                    229: {
                    230:        SV_InitBoxHull ();
                    231:        
                    232:        memset (sv_areanodes, 0, sizeof(sv_areanodes));
                    233:        sv_numareanodes = 0;
                    234:        SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs);
                    235: }
                    236: 
                    237: 
                    238: /*
                    239: ===============
                    240: SV_UnlinkEdict
                    241: 
                    242: ===============
                    243: */
                    244: void SV_UnlinkEdict (edict_t *ent)
                    245: {
                    246:        if (!ent->area.prev)
                    247:                return;         // not linked in anywhere
                    248:        RemoveLink (&ent->area);
                    249:        ent->area.prev = ent->area.next = NULL;
                    250: }
                    251: 
                    252: 
                    253: /*
                    254: ====================
                    255: SV_TouchLinks
                    256: ====================
                    257: */
                    258: void SV_TouchLinks ( edict_t *ent, areanode_t *node )
                    259: {
                    260:        link_t          *l, *next;
                    261:        edict_t         *touch;
                    262:        int                     old_self, old_other;
                    263: 
                    264: // touch linked edicts
                    265:        for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next)
                    266:        {
                    267:                next = l->next;
                    268:                touch = EDICT_FROM_AREA(l);
                    269:                if (touch == ent)
                    270:                        continue;
                    271:                if (!touch->v.touch || touch->v.solid != SOLID_TRIGGER)
                    272:                        continue;
                    273:                if (ent->v.absmin[0] > touch->v.absmax[0]
                    274:                || ent->v.absmin[1] > touch->v.absmax[1]
                    275:                || ent->v.absmin[2] > touch->v.absmax[2]
                    276:                || ent->v.absmax[0] < touch->v.absmin[0]
                    277:                || ent->v.absmax[1] < touch->v.absmin[1]
                    278:                || ent->v.absmax[2] < touch->v.absmin[2] )
                    279:                        continue;
                    280:                        
                    281:                old_self = pr_global_struct->self;
                    282:                old_other = pr_global_struct->other;
                    283: 
                    284:                pr_global_struct->self = EDICT_TO_PROG(touch);
                    285:                pr_global_struct->other = EDICT_TO_PROG(ent);
                    286:                pr_global_struct->time = sv.time;
                    287:                PR_ExecuteProgram (touch->v.touch);
                    288: 
                    289:                pr_global_struct->self = old_self;
                    290:                pr_global_struct->other = old_other;
                    291:        }
                    292:        
                    293: // recurse down both sides
                    294:        if (node->axis == -1)
                    295:                return;
                    296:        
                    297:        if ( ent->v.absmax[node->axis] > node->dist )
                    298:                SV_TouchLinks ( ent, node->children[0] );
                    299:        if ( ent->v.absmin[node->axis] < node->dist )
                    300:                SV_TouchLinks ( ent, node->children[1] );
                    301: }
                    302: 
                    303: 
                    304: /*
                    305: ===============
                    306: SV_FindTouchedLeafs
                    307: 
                    308: ===============
                    309: */
                    310: void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node)
                    311: {
                    312:        mplane_t        *splitplane;
                    313:        mleaf_t         *leaf;
                    314:        int                     sides;
                    315:        int                     leafnum;
                    316: 
                    317:        if (node->contents == CONTENTS_SOLID)
                    318:                return;
                    319:        
                    320: // add an efrag if the node is a leaf
                    321: 
                    322:        if ( node->contents < 0)
                    323:        {
                    324:                if (ent->num_leafs == MAX_ENT_LEAFS)
                    325:                        return;
                    326: 
                    327:                leaf = (mleaf_t *)node;
                    328:                leafnum = leaf - sv.worldmodel->leafs - 1;
                    329: 
                    330:                ent->leafnums[ent->num_leafs] = leafnum;
                    331:                ent->num_leafs++;                       
                    332:                return;
                    333:        }
                    334:        
                    335: // NODE_MIXED
                    336: 
                    337:        splitplane = node->plane;
                    338:        sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, splitplane);
                    339:        
                    340: // recurse down the contacted sides
                    341:        if (sides & 1)
                    342:                SV_FindTouchedLeafs (ent, node->children[0]);
                    343:                
                    344:        if (sides & 2)
                    345:                SV_FindTouchedLeafs (ent, node->children[1]);
                    346: }
                    347: 
                    348: /*
                    349: ===============
                    350: SV_LinkEdict
                    351: 
                    352: ===============
                    353: */
                    354: void SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
                    355: {
                    356:        areanode_t      *node;
                    357:        
                    358:        if (ent->area.prev)
                    359:                SV_UnlinkEdict (ent);   // unlink from old position
                    360:                
                    361:        if (ent == sv.edicts)
                    362:                return;         // don't add the world
                    363: 
                    364:        if (ent->free)
                    365:                return;
                    366: 
                    367: // set the abs box
                    368:        VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);  
                    369:        VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax);
                    370: 
                    371: //
                    372: // to make items easier to pick up and allow them to be grabbed off
                    373: // of shelves, the abs sizes are expanded
                    374: //
                    375:        if ((int)ent->v.flags & FL_ITEM)
                    376:        {
                    377:                ent->v.absmin[0] -= 15;
                    378:                ent->v.absmin[1] -= 15;
                    379:                ent->v.absmax[0] += 15;
                    380:                ent->v.absmax[1] += 15;
                    381:        }
                    382:        else
                    383:        {       // because movement is clipped an epsilon away from an actual edge,
                    384:                // we must fully check even when bounding boxes don't quite touch
                    385:                ent->v.absmin[0] -= 1;
                    386:                ent->v.absmin[1] -= 1;
                    387:                ent->v.absmin[2] -= 1;
                    388:                ent->v.absmax[0] += 1;
                    389:                ent->v.absmax[1] += 1;
                    390:                ent->v.absmax[2] += 1;
                    391:        }
                    392:        
                    393: // link to PVS leafs
                    394:        ent->num_leafs = 0;
                    395:        if (ent->v.modelindex)
                    396:                SV_FindTouchedLeafs (ent, sv.worldmodel->nodes);
                    397: 
                    398:        if (ent->v.solid == SOLID_NOT)
                    399:                return;
                    400: 
                    401: // find the first node that the ent's box crosses
                    402:        node = sv_areanodes;
                    403:        while (1)
                    404:        {
                    405:                if (node->axis == -1)
                    406:                        break;
                    407:                if (ent->v.absmin[node->axis] > node->dist)
                    408:                        node = node->children[0];
                    409:                else if (ent->v.absmax[node->axis] < node->dist)
                    410:                        node = node->children[1];
                    411:                else
                    412:                        break;          // crosses the node
                    413:        }
                    414:        
                    415: // link it in  
                    416: 
                    417:        if (ent->v.solid == SOLID_TRIGGER)
                    418:                InsertLinkBefore (&ent->area, &node->trigger_edicts);
                    419:        else
                    420:                InsertLinkBefore (&ent->area, &node->solid_edicts);
                    421:        
                    422: // if touch_triggers, touch all entities at this node and decend for more
                    423:        if (touch_triggers)
                    424:                SV_TouchLinks ( ent, sv_areanodes );
                    425: }
                    426: 
                    427: 
                    428: 
                    429: /*
                    430: ===============================================================================
                    431: 
                    432: POINT TESTING IN HULLS
                    433: 
                    434: ===============================================================================
                    435: */
                    436: 
                    437: #if    !id386
                    438: 
                    439: /*
                    440: ==================
                    441: SV_HullPointContents
                    442: 
                    443: ==================
                    444: */
                    445: int SV_HullPointContents (hull_t *hull, int num, vec3_t p)
                    446: {
                    447:        float           d;
                    448:        dclipnode_t     *node;
                    449:        mplane_t        *plane;
                    450: 
                    451:        while (num >= 0)
                    452:        {
                    453:                if (num < hull->firstclipnode || num > hull->lastclipnode)
                    454:                        Sys_Error ("SV_HullPointContents: bad node number");
                    455:        
                    456:                node = hull->clipnodes + num;
                    457:                plane = hull->planes + node->planenum;
                    458:                
                    459:                if (plane->type < 3)
                    460:                        d = p[plane->type] - plane->dist;
                    461:                else
                    462:                        d = DotProduct (plane->normal, p) - plane->dist;
                    463:                if (d < 0)
                    464:                        num = node->children[1];
                    465:                else
                    466:                        num = node->children[0];
                    467:        }
                    468:        
                    469:        return num;
                    470: }
                    471: 
                    472: #endif // !id386
                    473: 
                    474: 
                    475: /*
                    476: ==================
                    477: SV_PointContents
                    478: 
                    479: ==================
                    480: */
                    481: int SV_PointContents (vec3_t p)
                    482: {
                    483:        return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p);
                    484: }
                    485: 
                    486: //===========================================================================
                    487: 
                    488: /*
                    489: ============
                    490: SV_TestEntityPosition
                    491: 
                    492: A small wrapper around SV_BoxInSolidEntity that never clips against the
                    493: supplied entity.
                    494: ============
                    495: */
                    496: edict_t        *SV_TestEntityPosition (edict_t *ent)
                    497: {
                    498:        trace_t trace;
                    499: 
                    500:        trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent);
                    501:        
                    502:        if (trace.startsolid)
                    503:                return sv.edicts;
                    504:                
                    505:        return NULL;
                    506: }
                    507: 
                    508: 
                    509: /*
                    510: ===============================================================================
                    511: 
                    512: LINE TESTING IN HULLS
                    513: 
                    514: ===============================================================================
                    515: */
                    516: 
                    517: // 1/32 epsilon to keep floating point happy
                    518: #define        DIST_EPSILON    (0.03125)
                    519: 
                    520: /*
                    521: ==================
                    522: SV_RecursiveHullCheck
                    523: 
                    524: ==================
                    525: */
                    526: qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
                    527: {
                    528:        dclipnode_t     *node;
                    529:        mplane_t        *plane;
                    530:        float           t1, t2;
                    531:        float           frac;
                    532:        int                     i;
                    533:        vec3_t          mid;
                    534:        int                     side;
                    535:        float           midf;
                    536: 
                    537: // check for empty
                    538:        if (num < 0)
                    539:        {
                    540:                if (num != CONTENTS_SOLID)
                    541:                {
                    542:                        trace->allsolid = false;
                    543:                        if (num == CONTENTS_EMPTY)
                    544:                                trace->inopen = true;
                    545:                        else
                    546:                                trace->inwater = true;
                    547:                }
                    548:                else
                    549:                        trace->startsolid = true;
                    550:                return true;            // empty
                    551:        }
                    552: 
                    553:        if (num < hull->firstclipnode || num > hull->lastclipnode)
                    554:                Sys_Error ("SV_RecursiveHullCheck: bad node number");
                    555: 
                    556: //
                    557: // find the point distances
                    558: //
                    559:        node = hull->clipnodes + num;
                    560:        plane = hull->planes + node->planenum;
                    561: 
                    562:        if (plane->type < 3)
                    563:        {
                    564:                t1 = p1[plane->type] - plane->dist;
                    565:                t2 = p2[plane->type] - plane->dist;
                    566:        }
                    567:        else
                    568:        {
                    569:                t1 = DotProduct (plane->normal, p1) - plane->dist;
                    570:                t2 = DotProduct (plane->normal, p2) - plane->dist;
                    571:        }
                    572:        
                    573: #if 1
                    574:        if (t1 >= 0 && t2 >= 0)
                    575:                return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
                    576:        if (t1 < 0 && t2 < 0)
                    577:                return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
                    578: #else
                    579:        if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) )
                    580:                return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
                    581:        if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) )
                    582:                return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
                    583: #endif
                    584: 
                    585: // put the crosspoint DIST_EPSILON pixels on the near side
                    586:        if (t1 < 0)
                    587:                frac = (t1 + DIST_EPSILON)/(t1-t2);
                    588:        else
                    589:                frac = (t1 - DIST_EPSILON)/(t1-t2);
                    590:        if (frac < 0)
                    591:                frac = 0;
                    592:        if (frac > 1)
                    593:                frac = 1;
                    594:                
                    595:        midf = p1f + (p2f - p1f)*frac;
                    596:        for (i=0 ; i<3 ; i++)
                    597:                mid[i] = p1[i] + frac*(p2[i] - p1[i]);
                    598: 
                    599:        side = (t1 < 0);
                    600: 
                    601: // move up to the node
                    602:        if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
                    603:                return false;
                    604: 
                    605: #ifdef PARANOID
                    606:        if (SV_HullPointContents (sv_hullmodel, mid, node->children[side])
                    607:        == CONTENTS_SOLID)
                    608:        {
                    609:                Con_Printf ("mid PointInHullSolid\n");
                    610:                return false;
                    611:        }
                    612: #endif
                    613:        
                    614:        if (SV_HullPointContents (hull, node->children[side^1], mid)
                    615:        != CONTENTS_SOLID)
                    616: // go past the node
                    617:                return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
                    618:        
                    619:        if (trace->allsolid)
                    620:                return false;           // never got out of the solid area
                    621:                
                    622: //==================
                    623: // the other side of the node is solid, this is the impact point
                    624: //==================
                    625:        if (!side)
                    626:        {
                    627:                VectorCopy (plane->normal, trace->plane.normal);
                    628:                trace->plane.dist = plane->dist;
                    629:        }
                    630:        else
                    631:        {
                    632:                VectorSubtract (vec3_origin, plane->normal, trace->plane.normal);
                    633:                trace->plane.dist = -plane->dist;
                    634:        }
                    635: 
                    636:        while (SV_HullPointContents (hull, hull->firstclipnode, mid)
                    637:        == CONTENTS_SOLID)
                    638:        { // shouldn't really happen, but does occasionally
                    639:                frac -= 0.1;
                    640:                if (frac < 0)
                    641:                {
                    642:                        trace->fraction = midf;
                    643:                        VectorCopy (mid, trace->endpos);
                    644:                        Con_Printf ("backup past 0\n");
                    645:                        return false;
                    646:                }
                    647:                midf = p1f + (p2f - p1f)*frac;
                    648:                for (i=0 ; i<3 ; i++)
                    649:                        mid[i] = p1[i] + frac*(p2[i] - p1[i]);
                    650:        }
                    651: 
                    652:        trace->fraction = midf;
                    653:        VectorCopy (mid, trace->endpos);
                    654: 
                    655:        return false;
                    656: }
                    657: 
                    658: 
                    659: /*
                    660: ==================
                    661: SV_ClipMoveToEntity
                    662: 
                    663: Handles selection or creation of a clipping hull, and offseting (and
                    664: eventually rotation) of the end points
                    665: ==================
                    666: */
                    667: trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
                    668: {
                    669:        trace_t         trace;
                    670:        vec3_t          offset;
                    671:        vec3_t          start_l, end_l;
                    672:        hull_t          *hull;
                    673: 
                    674: // fill in a default trace
                    675:        memset (&trace, 0, sizeof(trace_t));
                    676:        trace.fraction = 1;
                    677:        trace.allsolid = true;
                    678:        VectorCopy (end, trace.endpos);
                    679: 
                    680: // get the clipping hull
                    681:        hull = SV_HullForEntity (ent, mins, maxs, offset);
                    682: 
                    683:        VectorSubtract (start, offset, start_l);
                    684:        VectorSubtract (end, offset, end_l);
                    685: 
                    686: // trace a line through the apropriate clipping hull
                    687:        SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
                    688: 
                    689: // fix trace up by the offset
                    690:        if (trace.fraction != 1)
                    691:                VectorAdd (trace.endpos, offset, trace.endpos);
                    692: 
                    693: // did we clip the move?
                    694:        if (trace.fraction < 1 || trace.startsolid  )
                    695:                trace.ent = ent;
                    696: 
                    697:        return trace;
                    698: }
                    699: 
                    700: //===========================================================================
                    701: 
                    702: /*
                    703: ====================
                    704: SV_ClipToLinks
                    705: 
                    706: Mins and maxs enclose the entire area swept by the move
                    707: ====================
                    708: */
                    709: void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip )
                    710: {
                    711:        link_t          *l, *next;
                    712:        edict_t         *touch;
                    713:        trace_t         trace;
                    714: 
                    715: // touch linked edicts
                    716:        for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next)
                    717:        {
                    718:                next = l->next;
                    719:                touch = EDICT_FROM_AREA(l);
                    720:                if (touch->v.solid == SOLID_NOT)
                    721:                        continue;
                    722:                if (touch == clip->passedict)
                    723:                        continue;
                    724:                if (touch->v.solid == SOLID_TRIGGER)
                    725:                        Sys_Error ("Trigger in clipping list");
                    726: 
                    727:                if (clip->type == MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP)
                    728:                        continue;
                    729: 
                    730:                if (clip->boxmins[0] > touch->v.absmax[0]
                    731:                || clip->boxmins[1] > touch->v.absmax[1]
                    732:                || clip->boxmins[2] > touch->v.absmax[2]
                    733:                || clip->boxmaxs[0] < touch->v.absmin[0]
                    734:                || clip->boxmaxs[1] < touch->v.absmin[1]
                    735:                || clip->boxmaxs[2] < touch->v.absmin[2] )
                    736:                        continue;
                    737: 
                    738:                if (clip->passedict && clip->passedict->v.size[0] && !touch->v.size[0])
                    739:                        continue;       // points never interact
                    740: 
                    741:        // might intersect, so do an exact clip
                    742:                if (clip->trace.allsolid)
                    743:                        return;
                    744:                if (clip->passedict)
                    745:                {
                    746:                        if (PROG_TO_EDICT(touch->v.owner) == clip->passedict)
                    747:                                continue;       // don't clip against own missiles
                    748:                        if (PROG_TO_EDICT(clip->passedict->v.owner) == touch)
                    749:                                continue;       // don't clip against owner
                    750:                }
                    751: 
                    752:                if ((int)touch->v.flags & FL_MONSTER)
                    753:                        trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end);
                    754:                else
                    755:                        trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end);
                    756:                if (trace.allsolid || trace.startsolid ||
                    757:                trace.fraction < clip->trace.fraction)
                    758:                {
                    759:                        trace.ent = touch;
                    760:                        if (clip->trace.startsolid)
                    761:                        {
                    762:                                clip->trace = trace;
                    763:                                clip->trace.startsolid = true;
                    764:                        }
                    765:                        else
                    766:                                clip->trace = trace;
                    767:                }
                    768:                else if (trace.startsolid)
                    769:                        clip->trace.startsolid = true;
                    770:        }
                    771:        
                    772: // recurse down both sides
                    773:        if (node->axis == -1)
                    774:                return;
                    775: 
                    776:        if ( clip->boxmaxs[node->axis] > node->dist )
                    777:                SV_ClipToLinks ( node->children[0], clip );
                    778:        if ( clip->boxmins[node->axis] < node->dist )
                    779:                SV_ClipToLinks ( node->children[1], clip );
                    780: }
                    781: 
                    782: 
                    783: /*
                    784: ==================
                    785: SV_MoveBounds
                    786: ==================
                    787: */
                    788: void SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs)
                    789: {
                    790: #if 0
                    791: // debug to test against everything
                    792: boxmins[0] = boxmins[1] = boxmins[2] = -9999;
                    793: boxmaxs[0] = boxmaxs[1] = boxmaxs[2] = 9999;
                    794: #else
                    795:        int             i;
                    796:        
                    797:        for (i=0 ; i<3 ; i++)
                    798:        {
                    799:                if (end[i] > start[i])
                    800:                {
                    801:                        boxmins[i] = start[i] + mins[i] - 1;
                    802:                        boxmaxs[i] = end[i] + maxs[i] + 1;
                    803:                }
                    804:                else
                    805:                {
                    806:                        boxmins[i] = end[i] + mins[i] - 1;
                    807:                        boxmaxs[i] = start[i] + maxs[i] + 1;
                    808:                }
                    809:        }
                    810: #endif
                    811: }
                    812: 
                    813: /*
                    814: ==================
                    815: SV_Move
                    816: ==================
                    817: */
                    818: trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict)
                    819: {
                    820:        moveclip_t      clip;
                    821:        int                     i;
                    822: 
                    823:        memset ( &clip, 0, sizeof ( moveclip_t ) );
                    824: 
                    825: // clip to world
                    826:        clip.trace = SV_ClipMoveToEntity ( sv.edicts, start, mins, maxs, end );
                    827: 
                    828:        clip.start = start;
                    829:        clip.end = end;
                    830:        clip.mins = mins;
                    831:        clip.maxs = maxs;
                    832:        clip.type = type;
                    833:        clip.passedict = passedict;
                    834: 
                    835:        if (type == MOVE_MISSILE)
                    836:        {
                    837:                for (i=0 ; i<3 ; i++)
                    838:                {
                    839:                        clip.mins2[i] = -15;
                    840:                        clip.maxs2[i] = 15;
                    841:                }
                    842:        }
                    843:        else
                    844:        {
                    845:                VectorCopy (mins, clip.mins2);
                    846:                VectorCopy (maxs, clip.maxs2);
                    847:        }
                    848:        
                    849: // create the bounding box of the entire move
                    850:        SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs );
                    851: 
                    852: // clip to entities
                    853:        SV_ClipToLinks ( sv_areanodes, &clip );
                    854: 
                    855:        return clip.trace;
                    856: }
                    857: 

unix.superglobalmegacorp.com

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