Annotation of quake1/world.c, revision 1.1.1.2

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:                old_self = pr_global_struct->self;
                    281:                old_other = pr_global_struct->other;
                    282: 
                    283:                pr_global_struct->self = EDICT_TO_PROG(touch);
                    284:                pr_global_struct->other = EDICT_TO_PROG(ent);
                    285:                pr_global_struct->time = sv.time;
                    286:                PR_ExecuteProgram (touch->v.touch);
                    287: 
                    288:                pr_global_struct->self = old_self;
                    289:                pr_global_struct->other = old_other;
                    290:        }
                    291:        
                    292: // recurse down both sides
                    293:        if (node->axis == -1)
                    294:                return;
                    295:        
                    296:        if ( ent->v.absmax[node->axis] > node->dist )
                    297:                SV_TouchLinks ( ent, node->children[0] );
                    298:        if ( ent->v.absmin[node->axis] < node->dist )
                    299:                SV_TouchLinks ( ent, node->children[1] );
                    300: }
                    301: 
                    302: 
                    303: /*
                    304: ===============
                    305: SV_FindTouchedLeafs
                    306: 
                    307: ===============
                    308: */
                    309: void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node)
                    310: {
                    311:        mplane_t        *splitplane;
                    312:        mleaf_t         *leaf;
                    313:        int                     sides;
                    314:        int                     leafnum;
                    315: 
                    316:        if (node->contents == CONTENTS_SOLID)
                    317:                return;
                    318:        
                    319: // add an efrag if the node is a leaf
                    320: 
                    321:        if ( node->contents < 0)
                    322:        {
                    323:                if (ent->num_leafs == MAX_ENT_LEAFS)
                    324:                        return;
                    325: 
                    326:                leaf = (mleaf_t *)node;
                    327:                leafnum = leaf - sv.worldmodel->leafs - 1;
                    328: 
                    329:                ent->leafnums[ent->num_leafs] = leafnum;
                    330:                ent->num_leafs++;                       
                    331:                return;
                    332:        }
                    333:        
                    334: // NODE_MIXED
                    335: 
                    336:        splitplane = node->plane;
                    337:        sides = BOX_ON_PLANE_SIDE(ent->v.absmin, ent->v.absmax, splitplane);
                    338:        
                    339: // recurse down the contacted sides
                    340:        if (sides & 1)
                    341:                SV_FindTouchedLeafs (ent, node->children[0]);
                    342:                
                    343:        if (sides & 2)
                    344:                SV_FindTouchedLeafs (ent, node->children[1]);
                    345: }
                    346: 
                    347: /*
                    348: ===============
                    349: SV_LinkEdict
                    350: 
                    351: ===============
                    352: */
                    353: void SV_LinkEdict (edict_t *ent, qboolean touch_triggers)
                    354: {
                    355:        areanode_t      *node;
1.1.1.2 ! root      356: 
1.1       root      357:        if (ent->area.prev)
                    358:                SV_UnlinkEdict (ent);   // unlink from old position
                    359:                
                    360:        if (ent == sv.edicts)
                    361:                return;         // don't add the world
                    362: 
                    363:        if (ent->free)
                    364:                return;
                    365: 
                    366: // set the abs box
1.1.1.2 ! root      367: 
        !           368: #ifdef QUAKE2
        !           369:        if (ent->v.solid == SOLID_BSP && 
        !           370:        (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) )
        !           371:        {       // expand for rotation
        !           372:                float           max, v;
        !           373:                int                     i;
        !           374: 
        !           375:                max = 0;
        !           376:                for (i=0 ; i<3 ; i++)
        !           377:                {
        !           378:                        v =fabs( ent->v.mins[i]);
        !           379:                        if (v > max)
        !           380:                                max = v;
        !           381:                        v =fabs( ent->v.maxs[i]);
        !           382:                        if (v > max)
        !           383:                                max = v;
        !           384:                }
        !           385:                for (i=0 ; i<3 ; i++)
        !           386:                {
        !           387:                        ent->v.absmin[i] = ent->v.origin[i] - max;
        !           388:                        ent->v.absmax[i] = ent->v.origin[i] + max;
        !           389:                }
        !           390:        }
        !           391:        else
        !           392: #endif
        !           393:        {
        !           394:                VectorAdd (ent->v.origin, ent->v.mins, ent->v.absmin);  
        !           395:                VectorAdd (ent->v.origin, ent->v.maxs, ent->v.absmax);
        !           396:        }
1.1       root      397: 
                    398: //
                    399: // to make items easier to pick up and allow them to be grabbed off
                    400: // of shelves, the abs sizes are expanded
                    401: //
                    402:        if ((int)ent->v.flags & FL_ITEM)
                    403:        {
                    404:                ent->v.absmin[0] -= 15;
                    405:                ent->v.absmin[1] -= 15;
                    406:                ent->v.absmax[0] += 15;
                    407:                ent->v.absmax[1] += 15;
                    408:        }
                    409:        else
                    410:        {       // because movement is clipped an epsilon away from an actual edge,
                    411:                // we must fully check even when bounding boxes don't quite touch
                    412:                ent->v.absmin[0] -= 1;
                    413:                ent->v.absmin[1] -= 1;
                    414:                ent->v.absmin[2] -= 1;
                    415:                ent->v.absmax[0] += 1;
                    416:                ent->v.absmax[1] += 1;
                    417:                ent->v.absmax[2] += 1;
                    418:        }
                    419:        
                    420: // link to PVS leafs
                    421:        ent->num_leafs = 0;
                    422:        if (ent->v.modelindex)
                    423:                SV_FindTouchedLeafs (ent, sv.worldmodel->nodes);
                    424: 
                    425:        if (ent->v.solid == SOLID_NOT)
                    426:                return;
                    427: 
                    428: // find the first node that the ent's box crosses
                    429:        node = sv_areanodes;
                    430:        while (1)
                    431:        {
                    432:                if (node->axis == -1)
                    433:                        break;
                    434:                if (ent->v.absmin[node->axis] > node->dist)
                    435:                        node = node->children[0];
                    436:                else if (ent->v.absmax[node->axis] < node->dist)
                    437:                        node = node->children[1];
                    438:                else
                    439:                        break;          // crosses the node
                    440:        }
                    441:        
                    442: // link it in  
                    443: 
                    444:        if (ent->v.solid == SOLID_TRIGGER)
                    445:                InsertLinkBefore (&ent->area, &node->trigger_edicts);
                    446:        else
                    447:                InsertLinkBefore (&ent->area, &node->solid_edicts);
                    448:        
                    449: // if touch_triggers, touch all entities at this node and decend for more
                    450:        if (touch_triggers)
                    451:                SV_TouchLinks ( ent, sv_areanodes );
                    452: }
                    453: 
                    454: 
                    455: 
                    456: /*
                    457: ===============================================================================
                    458: 
                    459: POINT TESTING IN HULLS
                    460: 
                    461: ===============================================================================
                    462: */
                    463: 
                    464: #if    !id386
                    465: 
                    466: /*
                    467: ==================
                    468: SV_HullPointContents
                    469: 
                    470: ==================
                    471: */
                    472: int SV_HullPointContents (hull_t *hull, int num, vec3_t p)
                    473: {
                    474:        float           d;
                    475:        dclipnode_t     *node;
                    476:        mplane_t        *plane;
                    477: 
                    478:        while (num >= 0)
                    479:        {
                    480:                if (num < hull->firstclipnode || num > hull->lastclipnode)
                    481:                        Sys_Error ("SV_HullPointContents: bad node number");
                    482:        
                    483:                node = hull->clipnodes + num;
                    484:                plane = hull->planes + node->planenum;
                    485:                
                    486:                if (plane->type < 3)
                    487:                        d = p[plane->type] - plane->dist;
                    488:                else
                    489:                        d = DotProduct (plane->normal, p) - plane->dist;
                    490:                if (d < 0)
                    491:                        num = node->children[1];
                    492:                else
                    493:                        num = node->children[0];
                    494:        }
                    495:        
                    496:        return num;
                    497: }
                    498: 
                    499: #endif // !id386
                    500: 
                    501: 
                    502: /*
                    503: ==================
                    504: SV_PointContents
                    505: 
                    506: ==================
                    507: */
                    508: int SV_PointContents (vec3_t p)
                    509: {
1.1.1.2 ! root      510:        int             cont;
        !           511: 
        !           512:        cont = SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p);
        !           513:        if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN)
        !           514:                cont = CONTENTS_WATER;
        !           515:        return cont;
        !           516: }
        !           517: 
        !           518: int SV_TruePointContents (vec3_t p)
        !           519: {
1.1       root      520:        return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p);
                    521: }
                    522: 
                    523: //===========================================================================
                    524: 
                    525: /*
                    526: ============
                    527: SV_TestEntityPosition
                    528: 
1.1.1.2 ! root      529: This could be a lot more efficient...
1.1       root      530: ============
                    531: */
                    532: edict_t        *SV_TestEntityPosition (edict_t *ent)
                    533: {
                    534:        trace_t trace;
                    535: 
                    536:        trace = SV_Move (ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, 0, ent);
                    537:        
                    538:        if (trace.startsolid)
                    539:                return sv.edicts;
                    540:                
                    541:        return NULL;
                    542: }
                    543: 
                    544: 
                    545: /*
                    546: ===============================================================================
                    547: 
                    548: LINE TESTING IN HULLS
                    549: 
                    550: ===============================================================================
                    551: */
                    552: 
                    553: // 1/32 epsilon to keep floating point happy
                    554: #define        DIST_EPSILON    (0.03125)
                    555: 
                    556: /*
                    557: ==================
                    558: SV_RecursiveHullCheck
                    559: 
                    560: ==================
                    561: */
                    562: qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
                    563: {
                    564:        dclipnode_t     *node;
                    565:        mplane_t        *plane;
                    566:        float           t1, t2;
                    567:        float           frac;
                    568:        int                     i;
                    569:        vec3_t          mid;
                    570:        int                     side;
                    571:        float           midf;
                    572: 
                    573: // check for empty
                    574:        if (num < 0)
                    575:        {
                    576:                if (num != CONTENTS_SOLID)
                    577:                {
                    578:                        trace->allsolid = false;
                    579:                        if (num == CONTENTS_EMPTY)
                    580:                                trace->inopen = true;
                    581:                        else
                    582:                                trace->inwater = true;
                    583:                }
                    584:                else
                    585:                        trace->startsolid = true;
                    586:                return true;            // empty
                    587:        }
                    588: 
                    589:        if (num < hull->firstclipnode || num > hull->lastclipnode)
                    590:                Sys_Error ("SV_RecursiveHullCheck: bad node number");
                    591: 
                    592: //
                    593: // find the point distances
                    594: //
                    595:        node = hull->clipnodes + num;
                    596:        plane = hull->planes + node->planenum;
                    597: 
                    598:        if (plane->type < 3)
                    599:        {
                    600:                t1 = p1[plane->type] - plane->dist;
                    601:                t2 = p2[plane->type] - plane->dist;
                    602:        }
                    603:        else
                    604:        {
                    605:                t1 = DotProduct (plane->normal, p1) - plane->dist;
                    606:                t2 = DotProduct (plane->normal, p2) - plane->dist;
                    607:        }
                    608:        
                    609: #if 1
                    610:        if (t1 >= 0 && t2 >= 0)
                    611:                return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
                    612:        if (t1 < 0 && t2 < 0)
                    613:                return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
                    614: #else
                    615:        if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) )
                    616:                return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
                    617:        if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) )
                    618:                return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
                    619: #endif
                    620: 
                    621: // put the crosspoint DIST_EPSILON pixels on the near side
                    622:        if (t1 < 0)
                    623:                frac = (t1 + DIST_EPSILON)/(t1-t2);
                    624:        else
                    625:                frac = (t1 - DIST_EPSILON)/(t1-t2);
                    626:        if (frac < 0)
                    627:                frac = 0;
                    628:        if (frac > 1)
                    629:                frac = 1;
                    630:                
                    631:        midf = p1f + (p2f - p1f)*frac;
                    632:        for (i=0 ; i<3 ; i++)
                    633:                mid[i] = p1[i] + frac*(p2[i] - p1[i]);
                    634: 
                    635:        side = (t1 < 0);
                    636: 
                    637: // move up to the node
                    638:        if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
                    639:                return false;
                    640: 
                    641: #ifdef PARANOID
                    642:        if (SV_HullPointContents (sv_hullmodel, mid, node->children[side])
                    643:        == CONTENTS_SOLID)
                    644:        {
                    645:                Con_Printf ("mid PointInHullSolid\n");
                    646:                return false;
                    647:        }
                    648: #endif
                    649:        
                    650:        if (SV_HullPointContents (hull, node->children[side^1], mid)
                    651:        != CONTENTS_SOLID)
                    652: // go past the node
                    653:                return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
                    654:        
                    655:        if (trace->allsolid)
                    656:                return false;           // never got out of the solid area
                    657:                
                    658: //==================
                    659: // the other side of the node is solid, this is the impact point
                    660: //==================
                    661:        if (!side)
                    662:        {
                    663:                VectorCopy (plane->normal, trace->plane.normal);
                    664:                trace->plane.dist = plane->dist;
                    665:        }
                    666:        else
                    667:        {
                    668:                VectorSubtract (vec3_origin, plane->normal, trace->plane.normal);
                    669:                trace->plane.dist = -plane->dist;
                    670:        }
                    671: 
                    672:        while (SV_HullPointContents (hull, hull->firstclipnode, mid)
                    673:        == CONTENTS_SOLID)
                    674:        { // shouldn't really happen, but does occasionally
                    675:                frac -= 0.1;
                    676:                if (frac < 0)
                    677:                {
                    678:                        trace->fraction = midf;
                    679:                        VectorCopy (mid, trace->endpos);
1.1.1.2 ! root      680:                        Con_DPrintf ("backup past 0\n");
1.1       root      681:                        return false;
                    682:                }
                    683:                midf = p1f + (p2f - p1f)*frac;
                    684:                for (i=0 ; i<3 ; i++)
                    685:                        mid[i] = p1[i] + frac*(p2[i] - p1[i]);
                    686:        }
                    687: 
                    688:        trace->fraction = midf;
                    689:        VectorCopy (mid, trace->endpos);
                    690: 
                    691:        return false;
                    692: }
                    693: 
                    694: 
                    695: /*
                    696: ==================
                    697: SV_ClipMoveToEntity
                    698: 
                    699: Handles selection or creation of a clipping hull, and offseting (and
                    700: eventually rotation) of the end points
                    701: ==================
                    702: */
                    703: trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end)
                    704: {
                    705:        trace_t         trace;
                    706:        vec3_t          offset;
                    707:        vec3_t          start_l, end_l;
                    708:        hull_t          *hull;
                    709: 
                    710: // fill in a default trace
                    711:        memset (&trace, 0, sizeof(trace_t));
                    712:        trace.fraction = 1;
                    713:        trace.allsolid = true;
                    714:        VectorCopy (end, trace.endpos);
                    715: 
                    716: // get the clipping hull
                    717:        hull = SV_HullForEntity (ent, mins, maxs, offset);
                    718: 
                    719:        VectorSubtract (start, offset, start_l);
                    720:        VectorSubtract (end, offset, end_l);
                    721: 
1.1.1.2 ! root      722: #ifdef QUAKE2
        !           723:        // rotate start and end into the models frame of reference
        !           724:        if (ent->v.solid == SOLID_BSP && 
        !           725:        (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) )
        !           726:        {
        !           727:                vec3_t  a;
        !           728:                vec3_t  forward, right, up;
        !           729:                vec3_t  temp;
        !           730: 
        !           731:                AngleVectors (ent->v.angles, forward, right, up);
        !           732: 
        !           733:                VectorCopy (start_l, temp);
        !           734:                start_l[0] = DotProduct (temp, forward);
        !           735:                start_l[1] = -DotProduct (temp, right);
        !           736:                start_l[2] = DotProduct (temp, up);
        !           737: 
        !           738:                VectorCopy (end_l, temp);
        !           739:                end_l[0] = DotProduct (temp, forward);
        !           740:                end_l[1] = -DotProduct (temp, right);
        !           741:                end_l[2] = DotProduct (temp, up);
        !           742:        }
        !           743: #endif
        !           744: 
1.1       root      745: // trace a line through the apropriate clipping hull
                    746:        SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
                    747: 
1.1.1.2 ! root      748: #ifdef QUAKE2
        !           749:        // rotate endpos back to world frame of reference
        !           750:        if (ent->v.solid == SOLID_BSP && 
        !           751:        (ent->v.angles[0] || ent->v.angles[1] || ent->v.angles[2]) )
        !           752:        {
        !           753:                vec3_t  a;
        !           754:                vec3_t  forward, right, up;
        !           755:                vec3_t  temp;
        !           756: 
        !           757:                if (trace.fraction != 1)
        !           758:                {
        !           759:                        VectorSubtract (vec3_origin, ent->v.angles, a);
        !           760:                        AngleVectors (a, forward, right, up);
        !           761: 
        !           762:                        VectorCopy (trace.endpos, temp);
        !           763:                        trace.endpos[0] = DotProduct (temp, forward);
        !           764:                        trace.endpos[1] = -DotProduct (temp, right);
        !           765:                        trace.endpos[2] = DotProduct (temp, up);
        !           766: 
        !           767:                        VectorCopy (trace.plane.normal, temp);
        !           768:                        trace.plane.normal[0] = DotProduct (temp, forward);
        !           769:                        trace.plane.normal[1] = -DotProduct (temp, right);
        !           770:                        trace.plane.normal[2] = DotProduct (temp, up);
        !           771:                }
        !           772:        }
        !           773: #endif
        !           774: 
1.1       root      775: // fix trace up by the offset
                    776:        if (trace.fraction != 1)
                    777:                VectorAdd (trace.endpos, offset, trace.endpos);
                    778: 
                    779: // did we clip the move?
                    780:        if (trace.fraction < 1 || trace.startsolid  )
                    781:                trace.ent = ent;
                    782: 
                    783:        return trace;
                    784: }
                    785: 
                    786: //===========================================================================
                    787: 
                    788: /*
                    789: ====================
                    790: SV_ClipToLinks
                    791: 
                    792: Mins and maxs enclose the entire area swept by the move
                    793: ====================
                    794: */
                    795: void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip )
                    796: {
                    797:        link_t          *l, *next;
                    798:        edict_t         *touch;
                    799:        trace_t         trace;
                    800: 
                    801: // touch linked edicts
                    802:        for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next)
                    803:        {
                    804:                next = l->next;
                    805:                touch = EDICT_FROM_AREA(l);
                    806:                if (touch->v.solid == SOLID_NOT)
                    807:                        continue;
                    808:                if (touch == clip->passedict)
                    809:                        continue;
                    810:                if (touch->v.solid == SOLID_TRIGGER)
                    811:                        Sys_Error ("Trigger in clipping list");
                    812: 
                    813:                if (clip->type == MOVE_NOMONSTERS && touch->v.solid != SOLID_BSP)
                    814:                        continue;
                    815: 
                    816:                if (clip->boxmins[0] > touch->v.absmax[0]
                    817:                || clip->boxmins[1] > touch->v.absmax[1]
                    818:                || clip->boxmins[2] > touch->v.absmax[2]
                    819:                || clip->boxmaxs[0] < touch->v.absmin[0]
                    820:                || clip->boxmaxs[1] < touch->v.absmin[1]
                    821:                || clip->boxmaxs[2] < touch->v.absmin[2] )
                    822:                        continue;
                    823: 
                    824:                if (clip->passedict && clip->passedict->v.size[0] && !touch->v.size[0])
                    825:                        continue;       // points never interact
                    826: 
                    827:        // might intersect, so do an exact clip
                    828:                if (clip->trace.allsolid)
                    829:                        return;
                    830:                if (clip->passedict)
                    831:                {
                    832:                        if (PROG_TO_EDICT(touch->v.owner) == clip->passedict)
                    833:                                continue;       // don't clip against own missiles
                    834:                        if (PROG_TO_EDICT(clip->passedict->v.owner) == touch)
                    835:                                continue;       // don't clip against owner
                    836:                }
                    837: 
                    838:                if ((int)touch->v.flags & FL_MONSTER)
                    839:                        trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end);
                    840:                else
                    841:                        trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end);
                    842:                if (trace.allsolid || trace.startsolid ||
                    843:                trace.fraction < clip->trace.fraction)
                    844:                {
                    845:                        trace.ent = touch;
                    846:                        if (clip->trace.startsolid)
                    847:                        {
                    848:                                clip->trace = trace;
                    849:                                clip->trace.startsolid = true;
                    850:                        }
                    851:                        else
                    852:                                clip->trace = trace;
                    853:                }
                    854:                else if (trace.startsolid)
                    855:                        clip->trace.startsolid = true;
                    856:        }
                    857:        
                    858: // recurse down both sides
                    859:        if (node->axis == -1)
                    860:                return;
                    861: 
                    862:        if ( clip->boxmaxs[node->axis] > node->dist )
                    863:                SV_ClipToLinks ( node->children[0], clip );
                    864:        if ( clip->boxmins[node->axis] < node->dist )
                    865:                SV_ClipToLinks ( node->children[1], clip );
                    866: }
                    867: 
                    868: 
                    869: /*
                    870: ==================
                    871: SV_MoveBounds
                    872: ==================
                    873: */
                    874: void SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs)
                    875: {
                    876: #if 0
                    877: // debug to test against everything
                    878: boxmins[0] = boxmins[1] = boxmins[2] = -9999;
                    879: boxmaxs[0] = boxmaxs[1] = boxmaxs[2] = 9999;
                    880: #else
                    881:        int             i;
                    882:        
                    883:        for (i=0 ; i<3 ; i++)
                    884:        {
                    885:                if (end[i] > start[i])
                    886:                {
                    887:                        boxmins[i] = start[i] + mins[i] - 1;
                    888:                        boxmaxs[i] = end[i] + maxs[i] + 1;
                    889:                }
                    890:                else
                    891:                {
                    892:                        boxmins[i] = end[i] + mins[i] - 1;
                    893:                        boxmaxs[i] = start[i] + maxs[i] + 1;
                    894:                }
                    895:        }
                    896: #endif
                    897: }
                    898: 
                    899: /*
                    900: ==================
                    901: SV_Move
                    902: ==================
                    903: */
                    904: trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict)
                    905: {
                    906:        moveclip_t      clip;
                    907:        int                     i;
                    908: 
                    909:        memset ( &clip, 0, sizeof ( moveclip_t ) );
                    910: 
                    911: // clip to world
                    912:        clip.trace = SV_ClipMoveToEntity ( sv.edicts, start, mins, maxs, end );
                    913: 
                    914:        clip.start = start;
                    915:        clip.end = end;
                    916:        clip.mins = mins;
                    917:        clip.maxs = maxs;
                    918:        clip.type = type;
                    919:        clip.passedict = passedict;
                    920: 
                    921:        if (type == MOVE_MISSILE)
                    922:        {
                    923:                for (i=0 ; i<3 ; i++)
                    924:                {
                    925:                        clip.mins2[i] = -15;
                    926:                        clip.maxs2[i] = 15;
                    927:                }
                    928:        }
                    929:        else
                    930:        {
                    931:                VectorCopy (mins, clip.mins2);
                    932:                VectorCopy (maxs, clip.maxs2);
                    933:        }
                    934:        
                    935: // create the bounding box of the entire move
                    936:        SV_MoveBounds ( start, clip.mins2, clip.maxs2, end, clip.boxmins, clip.boxmaxs );
                    937: 
                    938: // clip to entities
                    939:        SV_ClipToLinks ( sv_areanodes, &clip );
                    940: 
                    941:        return clip.trace;
                    942: }
                    943: 

unix.superglobalmegacorp.com

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