Annotation of quake2/qcommon/cmodel.c, revision 1.1.1.2

1.1       root        1: // cmodel.c -- model loading
1.1.1.2 ! root        2: 
1.1       root        3: #include "qcommon.h"
1.1.1.2 ! root        4: 
1.1       root        5: typedef struct
                      6: {
                      7:        cplane_t        *plane;
                      8:        int                     children[2];            // negative numbers are leafs
                      9: } cnode_t;
1.1.1.2 ! root       10: 
1.1       root       11: typedef struct
                     12: {
                     13:        cplane_t        *plane;
1.1.1.2 ! root       14:        mapsurface_t    *surface;
1.1       root       15: } cbrushside_t;
1.1.1.2 ! root       16: 
1.1       root       17: typedef struct
                     18: {
                     19:        int                     contents;
                     20:        int                     cluster;
                     21:        int                     area;
                     22:        unsigned short  firstleafbrush;
                     23:        unsigned short  numleafbrushes;
                     24: } cleaf_t;
1.1.1.2 ! root       25: 
1.1       root       26: typedef struct
                     27: {
                     28:        int                     contents;
                     29:        int                     numsides;
                     30:        int                     firstbrushside;
                     31:        int                     checkcount;             // to avoid repeated testings
                     32: } cbrush_t;
1.1.1.2 ! root       33: 
1.1       root       34: typedef struct
                     35: {
                     36:        int             numareaportals;
                     37:        int             firstareaportal;
                     38:        int             floodnum;                       // if two areas have equal floodnums, they are connected
                     39:        int             floodvalid;
                     40: } carea_t;
1.1.1.2 ! root       41: 
1.1       root       42: int                    checkcount;
1.1.1.2 ! root       43: 
1.1       root       44: char           map_name[MAX_QPATH];
1.1.1.2 ! root       45: 
1.1       root       46: int                    numbrushsides;
                     47: cbrushside_t map_brushsides[MAX_MAP_BRUSHSIDES];
1.1.1.2 ! root       48: 
1.1       root       49: int                    numtexinfo;
1.1.1.2 ! root       50: mapsurface_t   map_surfaces[MAX_MAP_TEXINFO];
        !            51: 
1.1       root       52: int                    numplanes;
                     53: cplane_t       map_planes[MAX_MAP_PLANES+6];           // extra for box hull
1.1.1.2 ! root       54: 
1.1       root       55: int                    numnodes;
                     56: cnode_t                map_nodes[MAX_MAP_NODES+6];             // extra for box hull
1.1.1.2 ! root       57: 
1.1       root       58: int                    numleafs = 1;   // allow leaf funcs to be called without a map
                     59: cleaf_t                map_leafs[MAX_MAP_LEAFS];
                     60: int                    emptyleaf, solidleaf;
1.1.1.2 ! root       61: 
1.1       root       62: int                    numleafbrushes;
                     63: unsigned short map_leafbrushes[MAX_MAP_LEAFBRUSHES];
1.1.1.2 ! root       64: 
1.1       root       65: int                    numcmodels;
                     66: cmodel_t       map_cmodels[MAX_MAP_MODELS];
1.1.1.2 ! root       67: 
1.1       root       68: int                    numbrushes;
                     69: cbrush_t       map_brushes[MAX_MAP_BRUSHES];
1.1.1.2 ! root       70: 
1.1       root       71: int                    numvisibility;
                     72: byte           map_visibility[MAX_MAP_VISIBILITY];
                     73: dvis_t         *map_vis = (dvis_t *)map_visibility;
1.1.1.2 ! root       74: 
1.1       root       75: int                    numentitychars;
                     76: char           map_entitystring[MAX_MAP_ENTSTRING];
1.1.1.2 ! root       77: 
1.1       root       78: int                    numareas = 1;
                     79: carea_t                map_areas[MAX_MAP_AREAS];
1.1.1.2 ! root       80: 
1.1       root       81: int                    numareaportals;
                     82: dareaportal_t map_areaportals[MAX_MAP_AREAPORTALS];
1.1.1.2 ! root       83: 
1.1       root       84: int                    numclusters = 1;
1.1.1.2 ! root       85: 
        !            86: mapsurface_t   nullsurface;
        !            87: 
1.1       root       88: int                    floodvalid;
1.1.1.2 ! root       89: 
1.1       root       90: qboolean       portalopen[MAX_MAP_AREAPORTALS];
1.1.1.2 ! root       91: 
        !            92: 
1.1       root       93: cvar_t         *map_noareas;
1.1.1.2 ! root       94: 
1.1       root       95: void   CM_InitBoxHull (void);
                     96: void   FloodAreaConnections (void);
1.1.1.2 ! root       97: 
        !            98: 
1.1       root       99: int            c_pointcontents;
                    100: int            c_traces, c_brush_traces;
1.1.1.2 ! root      101: 
        !           102: 
1.1       root      103: /*
                    104: ===============================================================================
1.1.1.2 ! root      105: 
1.1       root      106:                                        MAP LOADING
1.1.1.2 ! root      107: 
1.1       root      108: ===============================================================================
                    109: */
1.1.1.2 ! root      110: 
1.1       root      111: byte   *cmod_base;
1.1.1.2 ! root      112: 
1.1       root      113: /*
                    114: =================
                    115: CMod_LoadSubmodels
                    116: =================
                    117: */
                    118: void CMod_LoadSubmodels (lump_t *l)
                    119: {
                    120:        dmodel_t        *in;
                    121:        cmodel_t        *out;
                    122:        int                     i, j, count;
1.1.1.2 ! root      123: 
1.1       root      124:        in = (void *)(cmod_base + l->fileofs);
                    125:        if (l->filelen % sizeof(*in))
                    126:                Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
                    127:        count = l->filelen / sizeof(*in);
1.1.1.2 ! root      128: 
1.1       root      129:        if (count < 1)
                    130:                Com_Error (ERR_DROP, "Map with no models");
                    131:        if (count > MAX_MAP_MODELS)
                    132:                Com_Error (ERR_DROP, "Map has too many models");
1.1.1.2 ! root      133: 
1.1       root      134:        numcmodels = count;
1.1.1.2 ! root      135: 
1.1       root      136:        for ( i=0 ; i<count ; i++, in++, out++)
                    137:        {
                    138:                out = &map_cmodels[i];
1.1.1.2 ! root      139: 
1.1       root      140:                for (j=0 ; j<3 ; j++)
                    141:                {       // spread the mins / maxs by a pixel
                    142:                        out->mins[j] = LittleFloat (in->mins[j]) - 1;
                    143:                        out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
                    144:                        out->origin[j] = LittleFloat (in->origin[j]);
                    145:                }
                    146:                out->headnode = LittleLong (in->headnode);
                    147:        }
                    148: }
1.1.1.2 ! root      149: 
        !           150: 
1.1       root      151: /*
                    152: =================
                    153: CMod_LoadSurfaces
                    154: =================
                    155: */
                    156: void CMod_LoadSurfaces (lump_t *l)
                    157: {
                    158:        texinfo_t       *in;
1.1.1.2 ! root      159:        mapsurface_t    *out;
1.1       root      160:        int                     i, count;
1.1.1.2 ! root      161: 
1.1       root      162:        in = (void *)(cmod_base + l->fileofs);
                    163:        if (l->filelen % sizeof(*in))
                    164:                Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
                    165:        count = l->filelen / sizeof(*in);
                    166:        if (count < 1)
                    167:                Com_Error (ERR_DROP, "Map with no surfaces");
                    168:        if (count > MAX_MAP_TEXINFO)
                    169:                Com_Error (ERR_DROP, "Map has too many surfaces");
1.1.1.2 ! root      170: 
1.1       root      171:        numtexinfo = count;
                    172:        out = map_surfaces;
1.1.1.2 ! root      173: 
1.1       root      174:        for ( i=0 ; i<count ; i++, in++, out++)
                    175:        {
1.1.1.2 ! root      176:                strncpy (out->c.name, in->texture, sizeof(out->c.name)-1);
        !           177:                strncpy (out->rname, in->texture, sizeof(out->rname)-1);
        !           178:                out->c.flags = LittleLong (in->flags);
        !           179:                out->c.value = LittleLong (in->value);
1.1       root      180:        }
                    181: }
1.1.1.2 ! root      182: 
        !           183: 
1.1       root      184: /*
                    185: =================
                    186: CMod_LoadNodes
1.1.1.2 ! root      187: 
1.1       root      188: =================
                    189: */
                    190: void CMod_LoadNodes (lump_t *l)
                    191: {
                    192:        dnode_t         *in;
                    193:        int                     child;
                    194:        cnode_t         *out;
                    195:        int                     i, j, count;
                    196:        
                    197:        in = (void *)(cmod_base + l->fileofs);
                    198:        if (l->filelen % sizeof(*in))
                    199:                Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
                    200:        count = l->filelen / sizeof(*in);
1.1.1.2 ! root      201: 
1.1       root      202:        if (count < 1)
                    203:                Com_Error (ERR_DROP, "Map has no nodes");
                    204:        if (count > MAX_MAP_NODES)
                    205:                Com_Error (ERR_DROP, "Map has too many nodes");
1.1.1.2 ! root      206: 
1.1       root      207:        out = map_nodes;
1.1.1.2 ! root      208: 
1.1       root      209:        numnodes = count;
1.1.1.2 ! root      210: 
1.1       root      211:        for (i=0 ; i<count ; i++, out++, in++)
                    212:        {
                    213:                out->plane = map_planes + LittleLong(in->planenum);
                    214:                for (j=0 ; j<2 ; j++)
                    215:                {
                    216:                        child = LittleLong (in->children[j]);
                    217:                        out->children[j] = child;
                    218:                }
                    219:        }
1.1.1.2 ! root      220: 
1.1       root      221: }
1.1.1.2 ! root      222: 
1.1       root      223: /*
                    224: =================
                    225: CMod_LoadBrushes
1.1.1.2 ! root      226: 
1.1       root      227: =================
                    228: */
                    229: void CMod_LoadBrushes (lump_t *l)
                    230: {
                    231:        dbrush_t        *in;
                    232:        cbrush_t        *out;
                    233:        int                     i, count;
                    234:        
                    235:        in = (void *)(cmod_base + l->fileofs);
                    236:        if (l->filelen % sizeof(*in))
                    237:                Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
                    238:        count = l->filelen / sizeof(*in);
1.1.1.2 ! root      239: 
1.1       root      240:        if (count > MAX_MAP_BRUSHES)
                    241:                Com_Error (ERR_DROP, "Map has too many brushes");
1.1.1.2 ! root      242: 
1.1       root      243:        out = map_brushes;
1.1.1.2 ! root      244: 
1.1       root      245:        numbrushes = count;
1.1.1.2 ! root      246: 
1.1       root      247:        for (i=0 ; i<count ; i++, out++, in++)
                    248:        {
                    249:                out->firstbrushside = LittleLong(in->firstside);
                    250:                out->numsides = LittleLong(in->numsides);
                    251:                out->contents = LittleLong(in->contents);
                    252:        }
1.1.1.2 ! root      253: 
1.1       root      254: }
1.1.1.2 ! root      255: 
1.1       root      256: /*
                    257: =================
                    258: CMod_LoadLeafs
                    259: =================
                    260: */
                    261: void CMod_LoadLeafs (lump_t *l)
                    262: {
                    263:        int                     i;
                    264:        cleaf_t         *out;
                    265:        dleaf_t         *in;
                    266:        int                     count;
                    267:        
                    268:        in = (void *)(cmod_base + l->fileofs);
                    269:        if (l->filelen % sizeof(*in))
                    270:                Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
                    271:        count = l->filelen / sizeof(*in);
1.1.1.2 ! root      272: 
1.1       root      273:        if (count < 1)
                    274:                Com_Error (ERR_DROP, "Map with no leafs");
                    275:        // need to save space for box planes
                    276:        if (count > MAX_MAP_PLANES)
                    277:                Com_Error (ERR_DROP, "Map has too many planes");
1.1.1.2 ! root      278: 
1.1       root      279:        out = map_leafs;        
                    280:        numleafs = count;
                    281:        numclusters = 0;
1.1.1.2 ! root      282: 
1.1       root      283:        for ( i=0 ; i<count ; i++, in++, out++)
                    284:        {
                    285:                out->contents = LittleLong (in->contents);
                    286:                out->cluster = LittleShort (in->cluster);
                    287:                out->area = LittleShort (in->area);
                    288:                out->firstleafbrush = LittleShort (in->firstleafbrush);
                    289:                out->numleafbrushes = LittleShort (in->numleafbrushes);
1.1.1.2 ! root      290: 
1.1       root      291:                if (out->cluster >= numclusters)
                    292:                        numclusters = out->cluster + 1;
                    293:        }
1.1.1.2 ! root      294: 
1.1       root      295:        if (map_leafs[0].contents != CONTENTS_SOLID)
                    296:                Com_Error (ERR_DROP, "Map leaf 0 is not CONTENTS_SOLID");
                    297:        solidleaf = 0;
                    298:        emptyleaf = -1;
                    299:        for (i=1 ; i<numleafs ; i++)
                    300:        {
                    301:                if (!map_leafs[i].contents)
                    302:                {
                    303:                        emptyleaf = i;
                    304:                        break;
                    305:                }
                    306:        }
                    307:        if (emptyleaf == -1)
                    308:                Com_Error (ERR_DROP, "Map does not have an empty leaf");
                    309: }
1.1.1.2 ! root      310: 
1.1       root      311: /*
                    312: =================
                    313: CMod_LoadPlanes
                    314: =================
                    315: */
                    316: void CMod_LoadPlanes (lump_t *l)
                    317: {
                    318:        int                     i, j;
                    319:        cplane_t        *out;
                    320:        dplane_t        *in;
                    321:        int                     count;
                    322:        int                     bits;
                    323:        
                    324:        in = (void *)(cmod_base + l->fileofs);
                    325:        if (l->filelen % sizeof(*in))
                    326:                Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
                    327:        count = l->filelen / sizeof(*in);
1.1.1.2 ! root      328: 
1.1       root      329:        if (count < 1)
                    330:                Com_Error (ERR_DROP, "Map with no planes");
                    331:        // need to save space for box planes
                    332:        if (count > MAX_MAP_PLANES)
                    333:                Com_Error (ERR_DROP, "Map has too many planes");
1.1.1.2 ! root      334: 
1.1       root      335:        out = map_planes;       
                    336:        numplanes = count;
1.1.1.2 ! root      337: 
1.1       root      338:        for ( i=0 ; i<count ; i++, in++, out++)
                    339:        {
                    340:                bits = 0;
                    341:                for (j=0 ; j<3 ; j++)
                    342:                {
                    343:                        out->normal[j] = LittleFloat (in->normal[j]);
                    344:                        if (out->normal[j] < 0)
                    345:                                bits |= 1<<j;
                    346:                }
1.1.1.2 ! root      347: 
1.1       root      348:                out->dist = LittleFloat (in->dist);
                    349:                out->type = LittleLong (in->type);
                    350:                out->signbits = bits;
                    351:        }
                    352: }
1.1.1.2 ! root      353: 
1.1       root      354: /*
                    355: =================
                    356: CMod_LoadLeafBrushes
                    357: =================
                    358: */
                    359: void CMod_LoadLeafBrushes (lump_t *l)
                    360: {
                    361:        int                     i;
                    362:        unsigned short  *out;
                    363:        unsigned short  *in;
                    364:        int                     count;
                    365:        
                    366:        in = (void *)(cmod_base + l->fileofs);
                    367:        if (l->filelen % sizeof(*in))
                    368:                Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
                    369:        count = l->filelen / sizeof(*in);
1.1.1.2 ! root      370: 
1.1       root      371:        if (count < 1)
                    372:                Com_Error (ERR_DROP, "Map with no planes");
                    373:        // need to save space for box planes
                    374:        if (count > MAX_MAP_LEAFBRUSHES)
                    375:                Com_Error (ERR_DROP, "Map has too many leafbrushes");
1.1.1.2 ! root      376: 
1.1       root      377:        out = map_leafbrushes;
                    378:        numleafbrushes = count;
1.1.1.2 ! root      379: 
1.1       root      380:        for ( i=0 ; i<count ; i++, in++, out++)
                    381:                *out = LittleShort (*in);
                    382: }
1.1.1.2 ! root      383: 
1.1       root      384: /*
                    385: =================
                    386: CMod_LoadBrushSides
                    387: =================
                    388: */
                    389: void CMod_LoadBrushSides (lump_t *l)
                    390: {
                    391:        int                     i, j;
                    392:        cbrushside_t    *out;
                    393:        dbrushside_t    *in;
                    394:        int                     count;
                    395:        int                     num;
1.1.1.2 ! root      396: 
1.1       root      397:        in = (void *)(cmod_base + l->fileofs);
                    398:        if (l->filelen % sizeof(*in))
                    399:                Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
                    400:        count = l->filelen / sizeof(*in);
1.1.1.2 ! root      401: 
1.1       root      402:        // need to save space for box planes
                    403:        if (count > MAX_MAP_BRUSHSIDES)
                    404:                Com_Error (ERR_DROP, "Map has too many planes");
1.1.1.2 ! root      405: 
1.1       root      406:        out = map_brushsides;   
                    407:        numbrushsides = count;
1.1.1.2 ! root      408: 
1.1       root      409:        for ( i=0 ; i<count ; i++, in++, out++)
                    410:        {
                    411:                num = LittleShort (in->planenum);
                    412:                out->plane = &map_planes[num];
                    413:                j = LittleShort (in->texinfo);
                    414:                if (j >= numtexinfo)
                    415:                        Com_Error (ERR_DROP, "Bad brushside texinfo");
                    416:                out->surface = &map_surfaces[j];
                    417:        }
                    418: }
1.1.1.2 ! root      419: 
1.1       root      420: /*
                    421: =================
                    422: CMod_LoadAreas
                    423: =================
                    424: */
                    425: void CMod_LoadAreas (lump_t *l)
                    426: {
                    427:        int                     i;
                    428:        carea_t         *out;
                    429:        darea_t         *in;
                    430:        int                     count;
1.1.1.2 ! root      431: 
1.1       root      432:        in = (void *)(cmod_base + l->fileofs);
                    433:        if (l->filelen % sizeof(*in))
                    434:                Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
                    435:        count = l->filelen / sizeof(*in);
1.1.1.2 ! root      436: 
1.1       root      437:        if (count > MAX_MAP_AREAS)
                    438:                Com_Error (ERR_DROP, "Map has too many areas");
1.1.1.2 ! root      439: 
1.1       root      440:        out = map_areas;
                    441:        numareas = count;
1.1.1.2 ! root      442: 
1.1       root      443:        for ( i=0 ; i<count ; i++, in++, out++)
                    444:        {
                    445:                out->numareaportals = LittleLong (in->numareaportals);
                    446:                out->firstareaportal = LittleLong (in->firstareaportal);
                    447:                out->floodvalid = 0;
                    448:                out->floodnum = 0;
                    449:        }
                    450: }
1.1.1.2 ! root      451: 
1.1       root      452: /*
                    453: =================
                    454: CMod_LoadAreaPortals
                    455: =================
                    456: */
                    457: void CMod_LoadAreaPortals (lump_t *l)
                    458: {
                    459:        int                     i;
                    460:        dareaportal_t           *out;
                    461:        dareaportal_t   *in;
                    462:        int                     count;
1.1.1.2 ! root      463: 
1.1       root      464:        in = (void *)(cmod_base + l->fileofs);
                    465:        if (l->filelen % sizeof(*in))
                    466:                Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size");
                    467:        count = l->filelen / sizeof(*in);
1.1.1.2 ! root      468: 
1.1       root      469:        if (count > MAX_MAP_AREAS)
                    470:                Com_Error (ERR_DROP, "Map has too many areas");
1.1.1.2 ! root      471: 
1.1       root      472:        out = map_areaportals;
                    473:        numareaportals = count;
1.1.1.2 ! root      474: 
1.1       root      475:        for ( i=0 ; i<count ; i++, in++, out++)
                    476:        {
                    477:                out->portalnum = LittleLong (in->portalnum);
                    478:                out->otherarea = LittleLong (in->otherarea);
                    479:        }
                    480: }
1.1.1.2 ! root      481: 
1.1       root      482: /*
                    483: =================
                    484: CMod_LoadVisibility
                    485: =================
                    486: */
                    487: void CMod_LoadVisibility (lump_t *l)
                    488: {
                    489:        int             i;
1.1.1.2 ! root      490: 
1.1       root      491:        numvisibility = l->filelen;
                    492:        if (l->filelen > MAX_MAP_VISIBILITY)
                    493:                Com_Error (ERR_DROP, "Map has too large visibility lump");
1.1.1.2 ! root      494: 
1.1       root      495:        memcpy (map_visibility, cmod_base + l->fileofs, l->filelen);
1.1.1.2 ! root      496: 
1.1       root      497:        map_vis->numclusters = LittleLong (map_vis->numclusters);
                    498:        for (i=0 ; i<map_vis->numclusters ; i++)
                    499:        {
                    500:                map_vis->bitofs[i][0] = LittleLong (map_vis->bitofs[i][0]);
                    501:                map_vis->bitofs[i][1] = LittleLong (map_vis->bitofs[i][1]);
                    502:        }
                    503: }
1.1.1.2 ! root      504: 
        !           505: 
1.1       root      506: /*
                    507: =================
                    508: CMod_LoadEntityString
                    509: =================
                    510: */
                    511: void CMod_LoadEntityString (lump_t *l)
                    512: {
                    513:        numentitychars = l->filelen;
                    514:        if (l->filelen > MAX_MAP_ENTSTRING)
                    515:                Com_Error (ERR_DROP, "Map has too large entity lump");
1.1.1.2 ! root      516: 
1.1       root      517:        memcpy (map_entitystring, cmod_base + l->fileofs, l->filelen);
                    518: }
1.1.1.2 ! root      519: 
        !           520: 
        !           521: 
1.1       root      522: /*
                    523: ==================
                    524: CM_LoadMap
1.1.1.2 ! root      525: 
1.1       root      526: Loads in the map and all submodels
                    527: ==================
                    528: */
                    529: cmodel_t *CM_LoadMap (char *name, qboolean clientload, unsigned *checksum)
                    530: {
                    531:        unsigned                *buf;
                    532:        int                             i;
                    533:        dheader_t               header;
                    534:        int                             length;
                    535:        static unsigned last_checksum;
1.1.1.2 ! root      536: 
1.1       root      537:        map_noareas = Cvar_Get ("map_noareas", "0", 0);
1.1.1.2 ! root      538: 
1.1       root      539:        if (  !strcmp (map_name, name) && (clientload || !Cvar_VariableValue ("flushmap")) )
                    540:        {
                    541:                *checksum = last_checksum;
                    542:                if (!clientload)
                    543:                {
                    544:                        memset (portalopen, 0, sizeof(portalopen));
                    545:                        FloodAreaConnections ();
                    546:                }
                    547:                return &map_cmodels[0];         // still have the right version
                    548:        }
1.1.1.2 ! root      549: 
1.1       root      550:        // free old stuff
                    551:        numplanes = 0;
                    552:        numnodes = 0;
                    553:        numleafs = 0;
                    554:        numcmodels = 0;
                    555:        numvisibility = 0;
                    556:        numentitychars = 0;
                    557:        map_entitystring[0] = 0;
                    558:        map_name[0] = 0;
1.1.1.2 ! root      559: 
1.1       root      560:        if (!name || !name[0])
                    561:        {
                    562:                numleafs = 1;
                    563:                numclusters = 1;
                    564:                numareas = 1;
                    565:                *checksum = 0;
                    566:                return &map_cmodels[0];                 // cinematic servers won't have anything at all
                    567:        }
1.1.1.2 ! root      568: 
1.1       root      569:        //
                    570:        // load the file
                    571:        //
                    572:        length = FS_LoadFile (name, (void **)&buf);
                    573:        if (!buf)
                    574:                Com_Error (ERR_DROP, "Couldn't load %s", name);
                    575: 
                    576:        last_checksum = LittleLong (Com_BlockChecksum (buf, length));
                    577:        *checksum = last_checksum;
1.1.1.2 ! root      578: 
1.1       root      579:        header = *(dheader_t *)buf;
                    580:        for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
                    581:                ((int *)&header)[i] = LittleLong ( ((int *)&header)[i]);
1.1.1.2 ! root      582: 
1.1       root      583:        if (header.version != BSPVERSION)
                    584:                Com_Error (ERR_DROP, "CMod_LoadBrushModel: %s has wrong version number (%i should be %i)"
                    585:                , name, header.version, BSPVERSION);
1.1.1.2 ! root      586: 
1.1       root      587:        cmod_base = (byte *)buf;
1.1.1.2 ! root      588: 
1.1       root      589:        // load into heap
                    590:        CMod_LoadSurfaces (&header.lumps[LUMP_TEXINFO]);
                    591:        CMod_LoadLeafs (&header.lumps[LUMP_LEAFS]);
                    592:        CMod_LoadLeafBrushes (&header.lumps[LUMP_LEAFBRUSHES]);
                    593:        CMod_LoadPlanes (&header.lumps[LUMP_PLANES]);
                    594:        CMod_LoadBrushes (&header.lumps[LUMP_BRUSHES]);
                    595:        CMod_LoadBrushSides (&header.lumps[LUMP_BRUSHSIDES]);
                    596:        CMod_LoadSubmodels (&header.lumps[LUMP_MODELS]);
                    597:        CMod_LoadNodes (&header.lumps[LUMP_NODES]);
                    598:        CMod_LoadAreas (&header.lumps[LUMP_AREAS]);
                    599:        CMod_LoadAreaPortals (&header.lumps[LUMP_AREAPORTALS]);
                    600:        CMod_LoadVisibility (&header.lumps[LUMP_VISIBILITY]);
                    601:        CMod_LoadEntityString (&header.lumps[LUMP_ENTITIES]);
1.1.1.2 ! root      602: 
1.1       root      603:        FS_FreeFile (buf);
1.1.1.2 ! root      604: 
1.1       root      605:        CM_InitBoxHull ();
1.1.1.2 ! root      606: 
1.1       root      607:        memset (portalopen, 0, sizeof(portalopen));
                    608:        FloodAreaConnections ();
1.1.1.2 ! root      609: 
1.1       root      610:        strcpy (map_name, name);
1.1.1.2 ! root      611: 
1.1       root      612:        return &map_cmodels[0];
                    613: }
1.1.1.2 ! root      614: 
1.1       root      615: /*
                    616: ==================
                    617: CM_InlineModel
                    618: ==================
                    619: */
                    620: cmodel_t       *CM_InlineModel (char *name)
                    621: {
                    622:        int             num;
1.1.1.2 ! root      623: 
1.1       root      624:        if (!name || name[0] != '*')
                    625:                Com_Error (ERR_DROP, "CM_InlineModel: bad name");
                    626:        num = atoi (name+1);
                    627:        if (num < 1 || num >= numcmodels)
                    628:                Com_Error (ERR_DROP, "CM_InlineModel: bad number");
1.1.1.2 ! root      629: 
1.1       root      630:        return &map_cmodels[num];
                    631: }
1.1.1.2 ! root      632: 
1.1       root      633: int            CM_NumClusters (void)
                    634: {
                    635:        return numclusters;
                    636: }
1.1.1.2 ! root      637: 
1.1       root      638: int            CM_NumInlineModels (void)
                    639: {
                    640:        return numcmodels;
                    641: }
1.1.1.2 ! root      642: 
1.1       root      643: char   *CM_EntityString (void)
                    644: {
                    645:        return map_entitystring;
                    646: }
1.1.1.2 ! root      647: 
1.1       root      648: int            CM_LeafContents (int leafnum)
                    649: {
                    650:        if (leafnum < 0 || leafnum >= numleafs)
                    651:                Com_Error (ERR_DROP, "CM_LeafContents: bad number");
                    652:        return map_leafs[leafnum].contents;
                    653: }
1.1.1.2 ! root      654: 
1.1       root      655: int            CM_LeafCluster (int leafnum)
                    656: {
                    657:        if (leafnum < 0 || leafnum >= numleafs)
                    658:                Com_Error (ERR_DROP, "CM_LeafCluster: bad number");
                    659:        return map_leafs[leafnum].cluster;
                    660: }
1.1.1.2 ! root      661: 
1.1       root      662: int            CM_LeafArea (int leafnum)
                    663: {
                    664:        if (leafnum < 0 || leafnum >= numleafs)
                    665:                Com_Error (ERR_DROP, "CM_LeafArea: bad number");
                    666:        return map_leafs[leafnum].area;
                    667: }
1.1.1.2 ! root      668: 
1.1       root      669: //=======================================================================
1.1.1.2 ! root      670: 
        !           671: 
1.1       root      672: cplane_t       *box_planes;
                    673: int                    box_headnode;
                    674: cbrush_t       *box_brush;
                    675: cleaf_t                *box_leaf;
1.1.1.2 ! root      676: 
1.1       root      677: /*
                    678: ===================
                    679: CM_InitBoxHull
1.1.1.2 ! root      680: 
1.1       root      681: Set up the planes and nodes so that the six floats of a bounding box
                    682: can just be stored out and get a proper clipping hull structure.
                    683: ===================
                    684: */
                    685: void CM_InitBoxHull (void)
                    686: {
                    687:        int                     i;
                    688:        int                     side;
                    689:        cnode_t         *c;
                    690:        cplane_t        *p;
                    691:        cbrushside_t    *s;
1.1.1.2 ! root      692: 
1.1       root      693:        box_headnode = numnodes;
                    694:        box_planes = &map_planes[numplanes];
                    695:        if (numnodes+6 > MAX_MAP_NODES
                    696:                || numbrushes+1 > MAX_MAP_BRUSHES
                    697:                || numleafbrushes+1 > MAX_MAP_LEAFBRUSHES
                    698:                || numbrushsides+6 > MAX_MAP_BRUSHSIDES
                    699:                || numplanes+12 > MAX_MAP_PLANES)
                    700:                Com_Error (ERR_DROP, "Not enough room for box tree");
1.1.1.2 ! root      701: 
1.1       root      702:        box_brush = &map_brushes[numbrushes];
                    703:        box_brush->numsides = 6;
                    704:        box_brush->firstbrushside = numbrushsides;
                    705:        box_brush->contents = CONTENTS_MONSTER;
1.1.1.2 ! root      706: 
1.1       root      707:        box_leaf = &map_leafs[numleafs];
                    708:        box_leaf->contents = CONTENTS_MONSTER;
                    709:        box_leaf->firstleafbrush = numleafbrushes;
                    710:        box_leaf->numleafbrushes = 1;
1.1.1.2 ! root      711: 
1.1       root      712:        map_leafbrushes[numleafbrushes] = numbrushes;
1.1.1.2 ! root      713: 
1.1       root      714:        for (i=0 ; i<6 ; i++)
                    715:        {
                    716:                side = i&1;
1.1.1.2 ! root      717: 
1.1       root      718:                // brush sides
                    719:                s = &map_brushsides[numbrushsides+i];
                    720:                s->plane =      map_planes + (numplanes+i*2+side);
                    721:                s->surface = &nullsurface;
1.1.1.2 ! root      722: 
1.1       root      723:                // nodes
                    724:                c = &map_nodes[box_headnode+i];
                    725:                c->plane = map_planes + (numplanes+i*2);
                    726:                c->children[side] = -1 - emptyleaf;
                    727:                if (i != 5)
                    728:                        c->children[side^1] = box_headnode+i + 1;
                    729:                else
                    730:                        c->children[side^1] = -1 - numleafs;
1.1.1.2 ! root      731: 
1.1       root      732:                // planes
                    733:                p = &box_planes[i*2];
                    734:                p->type = i>>1;
                    735:                p->signbits = 0;
                    736:                VectorClear (p->normal);
                    737:                p->normal[i>>1] = 1;
1.1.1.2 ! root      738: 
1.1       root      739:                p = &box_planes[i*2+1];
                    740:                p->type = 3 + (i>>1);
                    741:                p->signbits = 0;
                    742:                VectorClear (p->normal);
                    743:                p->normal[i>>1] = -1;
                    744:        }       
                    745: }
1.1.1.2 ! root      746: 
        !           747: 
1.1       root      748: /*
                    749: ===================
                    750: CM_HeadnodeForBox
1.1.1.2 ! root      751: 
1.1       root      752: To keep everything totally uniform, bounding boxes are turned into small
                    753: BSP trees instead of being compared directly.
                    754: ===================
                    755: */
                    756: int    CM_HeadnodeForBox (vec3_t mins, vec3_t maxs)
                    757: {
                    758:        box_planes[0].dist = maxs[0];
                    759:        box_planes[1].dist = -maxs[0];
                    760:        box_planes[2].dist = mins[0];
                    761:        box_planes[3].dist = -mins[0];
                    762:        box_planes[4].dist = maxs[1];
                    763:        box_planes[5].dist = -maxs[1];
                    764:        box_planes[6].dist = mins[1];
                    765:        box_planes[7].dist = -mins[1];
                    766:        box_planes[8].dist = maxs[2];
                    767:        box_planes[9].dist = -maxs[2];
                    768:        box_planes[10].dist = mins[2];
                    769:        box_planes[11].dist = -mins[2];
1.1.1.2 ! root      770: 
1.1       root      771:        return box_headnode;
                    772: }
1.1.1.2 ! root      773: 
        !           774: 
1.1       root      775: /*
                    776: ==================
                    777: CM_PointLeafnum_r
1.1.1.2 ! root      778: 
1.1       root      779: ==================
                    780: */
                    781: int CM_PointLeafnum_r (vec3_t p, int num)
                    782: {
                    783:        float           d;
                    784:        cnode_t         *node;
                    785:        cplane_t        *plane;
1.1.1.2 ! root      786: 
1.1       root      787:        while (num >= 0)
                    788:        {
                    789:                node = map_nodes + num;
                    790:                plane = node->plane;
                    791:                
                    792:                if (plane->type < 3)
                    793:                        d = p[plane->type] - plane->dist;
                    794:                else
                    795:                        d = DotProduct (plane->normal, p) - plane->dist;
                    796:                if (d < 0)
                    797:                        num = node->children[1];
                    798:                else
                    799:                        num = node->children[0];
                    800:        }
1.1.1.2 ! root      801: 
1.1       root      802:        c_pointcontents++;              // optimize counter
1.1.1.2 ! root      803: 
1.1       root      804:        return -1 - num;
                    805: }
1.1.1.2 ! root      806: 
1.1       root      807: int CM_PointLeafnum (vec3_t p)
                    808: {
                    809:        if (!numplanes)
                    810:                return 0;               // sound may call this without map loaded
                    811:        return CM_PointLeafnum_r (p, 0);
                    812: }
1.1.1.2 ! root      813: 
        !           814: 
        !           815: 
1.1       root      816: /*
                    817: =============
                    818: CM_BoxLeafnums
1.1.1.2 ! root      819: 
1.1       root      820: Fills in a list of all the leafs touched
                    821: =============
                    822: */
                    823: int            leaf_count, leaf_maxcount;
                    824: int            *leaf_list;
                    825: float  *leaf_mins, *leaf_maxs;
                    826: int            leaf_topnode;
1.1.1.2 ! root      827: 
1.1       root      828: void CM_BoxLeafnums_r (int nodenum)
                    829: {
                    830:        cplane_t        *plane;
                    831:        cnode_t         *node;
                    832:        int             s;
1.1.1.2 ! root      833: 
1.1       root      834:        while (1)
                    835:        {
                    836:                if (nodenum < 0)
                    837:                {
                    838:                        if (leaf_count >= leaf_maxcount)
                    839:                        {
                    840: //                             Com_Printf ("CM_BoxLeafnums_r: overflow\n");
                    841:                                return;
                    842:                        }
                    843:                        leaf_list[leaf_count++] = -1 - nodenum;
                    844:                        return;
                    845:                }
                    846:        
                    847:                node = &map_nodes[nodenum];
                    848:                plane = node->plane;
                    849: //             s = BoxOnPlaneSide (leaf_mins, leaf_maxs, plane);
                    850:                s = BOX_ON_PLANE_SIDE(leaf_mins, leaf_maxs, plane);
                    851:                if (s == 1)
                    852:                        nodenum = node->children[0];
                    853:                else if (s == 2)
                    854:                        nodenum = node->children[1];
                    855:                else
                    856:                {       // go down both
                    857:                        if (leaf_topnode == -1)
                    858:                                leaf_topnode = nodenum;
                    859:                        CM_BoxLeafnums_r (node->children[0]);
                    860:                        nodenum = node->children[1];
                    861:                }
1.1.1.2 ! root      862: 
1.1       root      863:        }
                    864: }
1.1.1.2 ! root      865: 
1.1       root      866: int    CM_BoxLeafnums_headnode (vec3_t mins, vec3_t maxs, int *list, int listsize, int headnode, int *topnode)
                    867: {
                    868:        leaf_list = list;
                    869:        leaf_count = 0;
                    870:        leaf_maxcount = listsize;
                    871:        leaf_mins = mins;
                    872:        leaf_maxs = maxs;
1.1.1.2 ! root      873: 
1.1       root      874:        leaf_topnode = -1;
1.1.1.2 ! root      875: 
1.1       root      876:        CM_BoxLeafnums_r (headnode);
1.1.1.2 ! root      877: 
1.1       root      878:        if (topnode)
                    879:                *topnode = leaf_topnode;
1.1.1.2 ! root      880: 
1.1       root      881:        return leaf_count;
                    882: }
1.1.1.2 ! root      883: 
1.1       root      884: int    CM_BoxLeafnums (vec3_t mins, vec3_t maxs, int *list, int listsize, int *topnode)
                    885: {
                    886:        return CM_BoxLeafnums_headnode (mins, maxs, list,
                    887:                listsize, map_cmodels[0].headnode, topnode);
                    888: }
1.1.1.2 ! root      889: 
        !           890: 
        !           891: 
1.1       root      892: /*
                    893: ==================
                    894: CM_PointContents
1.1.1.2 ! root      895: 
1.1       root      896: ==================
                    897: */
                    898: int CM_PointContents (vec3_t p, int headnode)
                    899: {
                    900:        int             l;
1.1.1.2 ! root      901: 
1.1       root      902:        if (!numnodes)  // map not loaded
                    903:                return 0;
                    904: 
                    905:        l = CM_PointLeafnum_r (p, headnode);
1.1.1.2 ! root      906: 
1.1       root      907:        return map_leafs[l].contents;
                    908: }
1.1.1.2 ! root      909: 
1.1       root      910: /*
                    911: ==================
                    912: CM_TransformedPointContents
1.1.1.2 ! root      913: 
1.1       root      914: Handles offseting and rotation of the end points for moving and
                    915: rotating entities
                    916: ==================
                    917: */
                    918: int    CM_TransformedPointContents (vec3_t p, int headnode, vec3_t origin, vec3_t angles)
                    919: {
                    920:        vec3_t          p_l;
                    921:        vec3_t          temp;
                    922:        vec3_t          forward, right, up;
                    923:        int                     l;
1.1.1.2 ! root      924: 
1.1       root      925:        // subtract origin offset
                    926:        VectorSubtract (p, origin, p_l);
1.1.1.2 ! root      927: 
1.1       root      928:        // rotate start and end into the models frame of reference
                    929:        if (headnode != box_headnode && 
                    930:        (angles[0] || angles[1] || angles[2]) )
                    931:        {
                    932:                AngleVectors (angles, forward, right, up);
1.1.1.2 ! root      933: 
1.1       root      934:                VectorCopy (p_l, temp);
                    935:                p_l[0] = DotProduct (temp, forward);
                    936:                p_l[1] = -DotProduct (temp, right);
                    937:                p_l[2] = DotProduct (temp, up);
                    938:        }
1.1.1.2 ! root      939: 
1.1       root      940:        l = CM_PointLeafnum_r (p_l, headnode);
1.1.1.2 ! root      941: 
1.1       root      942:        return map_leafs[l].contents;
                    943: }
1.1.1.2 ! root      944: 
        !           945: 
1.1       root      946: /*
                    947: ===============================================================================
1.1.1.2 ! root      948: 
1.1       root      949: BOX TRACING
1.1.1.2 ! root      950: 
1.1       root      951: ===============================================================================
                    952: */
1.1.1.2 ! root      953: 
1.1       root      954: // 1/32 epsilon to keep floating point happy
                    955: #define        DIST_EPSILON    (0.03125)
1.1.1.2 ! root      956: 
1.1       root      957: vec3_t trace_start, trace_end;
                    958: vec3_t trace_mins, trace_maxs;
                    959: vec3_t trace_extents;
1.1.1.2 ! root      960: 
1.1       root      961: trace_t        trace_trace;
                    962: int            trace_contents;
                    963: qboolean       trace_ispoint;          // optimized case
1.1.1.2 ! root      964: 
1.1       root      965: /*
                    966: ================
                    967: CM_ClipBoxToBrush
                    968: ================
                    969: */
                    970: void CM_ClipBoxToBrush (vec3_t mins, vec3_t maxs, vec3_t p1, vec3_t p2,
                    971:                                          trace_t *trace, cbrush_t *brush)
                    972: {
                    973:        int                     i, j;
                    974:        cplane_t        *plane, *clipplane;
                    975:        float           dist;
                    976:        float           enterfrac, leavefrac;
                    977:        vec3_t          ofs;
                    978:        float           d1, d2;
                    979:        qboolean        getout, startout;
                    980:        float           f;
                    981:        cbrushside_t    *side, *leadside;
                    982: 
                    983:        enterfrac = -1;
                    984:        leavefrac = 1;
                    985:        clipplane = NULL;
                    986: 
                    987:        if (!brush->numsides)
                    988:                return;
                    989: 
                    990:        c_brush_traces++;
                    991: 
                    992:        getout = false;
                    993:        startout = false;
                    994:        leadside = NULL;
                    995: 
                    996:        for (i=0 ; i<brush->numsides ; i++)
                    997:        {
                    998:                side = &map_brushsides[brush->firstbrushside+i];
                    999:                plane = side->plane;
                   1000: 
                   1001:                // FIXME: special case for axial
                   1002: 
                   1003:                if (!trace_ispoint)
                   1004:                {       // general box case
                   1005: 
                   1006:                        // push the plane out apropriately for mins/maxs
                   1007: 
                   1008:                        // FIXME: use signbits into 8 way lookup for each mins/maxs
                   1009:                        for (j=0 ; j<3 ; j++)
                   1010:                        {
                   1011:                                if (plane->normal[j] < 0)
                   1012:                                        ofs[j] = maxs[j];
                   1013:                                else
                   1014:                                        ofs[j] = mins[j];
                   1015:                        }
                   1016:                        dist = DotProduct (ofs, plane->normal);
                   1017:                        dist = plane->dist - dist;
                   1018:                }
                   1019:                else
                   1020:                {       // special point case
                   1021:                        dist = plane->dist;
                   1022:                }
                   1023: 
                   1024:                d1 = DotProduct (p1, plane->normal) - dist;
                   1025:                d2 = DotProduct (p2, plane->normal) - dist;
                   1026: 
                   1027:                if (d2 > 0)
                   1028:                        getout = true;  // endpoint is not in solid
                   1029:                if (d1 > 0)
                   1030:                        startout = true;
                   1031: 
                   1032:                // if completely in front of face, no intersection
                   1033:                if (d1 > 0 && d2 >= d1)
                   1034:                        return;
                   1035: 
                   1036:                if (d1 <= 0 && d2 <= 0)
                   1037:                        continue;
                   1038: 
                   1039:                // crosses face
                   1040:                if (d1 > d2)
                   1041:                {       // enter
                   1042:                        f = (d1-DIST_EPSILON) / (d1-d2);
                   1043:                        if (f > enterfrac)
                   1044:                        {
                   1045:                                enterfrac = f;
                   1046:                                clipplane = plane;
                   1047:                                leadside = side;
                   1048:                        }
                   1049:                }
                   1050:                else
                   1051:                {       // leave
                   1052:                        f = (d1+DIST_EPSILON) / (d1-d2);
                   1053:                        if (f < leavefrac)
                   1054:                                leavefrac = f;
                   1055:                }
                   1056:        }
                   1057: 
                   1058:        if (!startout)
                   1059:        {       // original point was inside brush
                   1060:                trace->startsolid = true;
                   1061:                if (!getout)
                   1062:                        trace->allsolid = true;
                   1063:                return;
                   1064:        }
                   1065:        if (enterfrac < leavefrac)
                   1066:        {
                   1067:                if (enterfrac > -1 && enterfrac < trace->fraction)
                   1068:                {
                   1069:                        if (enterfrac < 0)
                   1070:                                enterfrac = 0;
                   1071:                        trace->fraction = enterfrac;
                   1072:                        trace->plane = *clipplane;
1.1.1.2 ! root     1073:                        trace->surface = &(leadside->surface->c);
1.1       root     1074:                        trace->contents = brush->contents;
                   1075:                }
                   1076:        }
                   1077: }
                   1078: 
                   1079: /*
                   1080: ================
                   1081: CM_TestBoxInBrush
                   1082: ================
                   1083: */
                   1084: void CM_TestBoxInBrush (vec3_t mins, vec3_t maxs, vec3_t p1,
                   1085:                                          trace_t *trace, cbrush_t *brush)
                   1086: {
                   1087:        int                     i, j;
                   1088:        cplane_t        *plane;
                   1089:        float           dist;
                   1090:        vec3_t          ofs;
                   1091:        float           d1;
                   1092:        cbrushside_t    *side;
                   1093: 
                   1094:        if (!brush->numsides)
                   1095:                return;
                   1096: 
                   1097:        for (i=0 ; i<brush->numsides ; i++)
                   1098:        {
                   1099:                side = &map_brushsides[brush->firstbrushside+i];
                   1100:                plane = side->plane;
                   1101: 
                   1102:                // FIXME: special case for axial
                   1103: 
                   1104:                // general box case
                   1105: 
                   1106:                // push the plane out apropriately for mins/maxs
                   1107: 
                   1108:                // FIXME: use signbits into 8 way lookup for each mins/maxs
                   1109:                for (j=0 ; j<3 ; j++)
                   1110:                {
                   1111:                        if (plane->normal[j] < 0)
                   1112:                                ofs[j] = maxs[j];
                   1113:                        else
                   1114:                                ofs[j] = mins[j];
                   1115:                }
                   1116:                dist = DotProduct (ofs, plane->normal);
                   1117:                dist = plane->dist - dist;
                   1118: 
                   1119:                d1 = DotProduct (p1, plane->normal) - dist;
                   1120: 
                   1121:                // if completely in front of face, no intersection
                   1122:                if (d1 > 0)
                   1123:                        return;
                   1124: 
                   1125:        }
                   1126: 
                   1127:        // inside this brush
                   1128:        trace->startsolid = trace->allsolid = true;
                   1129:        trace->fraction = 0;
                   1130:        trace->contents = brush->contents;
                   1131: }
                   1132: 
1.1.1.2 ! root     1133: 
1.1       root     1134: /*
                   1135: ================
                   1136: CM_TraceToLeaf
                   1137: ================
                   1138: */
                   1139: void CM_TraceToLeaf (int leafnum)
                   1140: {
                   1141:        int                     k;
                   1142:        int                     brushnum;
                   1143:        cleaf_t         *leaf;
                   1144:        cbrush_t        *b;
                   1145: 
                   1146:        leaf = &map_leafs[leafnum];
                   1147:        if ( !(leaf->contents & trace_contents))
                   1148:                return;
                   1149:        // trace line against all brushes in the leaf
                   1150:        for (k=0 ; k<leaf->numleafbrushes ; k++)
                   1151:        {
                   1152:                brushnum = map_leafbrushes[leaf->firstleafbrush+k];
                   1153:                b = &map_brushes[brushnum];
                   1154:                if (b->checkcount == checkcount)
                   1155:                        continue;       // already checked this brush in another leaf
                   1156:                b->checkcount = checkcount;
                   1157: 
                   1158:                if ( !(b->contents & trace_contents))
                   1159:                        continue;
                   1160:                CM_ClipBoxToBrush (trace_mins, trace_maxs, trace_start, trace_end, &trace_trace, b);
                   1161:                if (!trace_trace.fraction)
                   1162:                        return;
                   1163:        }
                   1164: 
                   1165: }
                   1166: 
                   1167: 
                   1168: /*
                   1169: ================
                   1170: CM_TestInLeaf
                   1171: ================
                   1172: */
                   1173: void CM_TestInLeaf (int leafnum)
                   1174: {
                   1175:        int                     k;
                   1176:        int                     brushnum;
                   1177:        cleaf_t         *leaf;
                   1178:        cbrush_t        *b;
                   1179: 
                   1180:        leaf = &map_leafs[leafnum];
                   1181:        if ( !(leaf->contents & trace_contents))
                   1182:                return;
                   1183:        // trace line against all brushes in the leaf
                   1184:        for (k=0 ; k<leaf->numleafbrushes ; k++)
                   1185:        {
                   1186:                brushnum = map_leafbrushes[leaf->firstleafbrush+k];
                   1187:                b = &map_brushes[brushnum];
                   1188:                if (b->checkcount == checkcount)
                   1189:                        continue;       // already checked this brush in another leaf
                   1190:                b->checkcount = checkcount;
                   1191: 
                   1192:                if ( !(b->contents & trace_contents))
                   1193:                        continue;
                   1194:                CM_TestBoxInBrush (trace_mins, trace_maxs, trace_start, &trace_trace, b);
                   1195:                if (!trace_trace.fraction)
                   1196:                        return;
                   1197:        }
                   1198: 
                   1199: }
                   1200: 
                   1201: 
                   1202: /*
                   1203: ==================
                   1204: CM_RecursiveHullCheck
1.1.1.2 ! root     1205: 
1.1       root     1206: ==================
                   1207: */
                   1208: void CM_RecursiveHullCheck (int num, float p1f, float p2f, vec3_t p1, vec3_t p2)
                   1209: {
                   1210:        cnode_t         *node;
                   1211:        cplane_t        *plane;
                   1212:        float           t1, t2, offset;
                   1213:        float           frac, frac2;
                   1214:        float           idist;
                   1215:        int                     i;
                   1216:        vec3_t          mid;
                   1217:        int                     side;
                   1218:        float           midf;
1.1.1.2 ! root     1219: 
1.1       root     1220:        if (trace_trace.fraction <= p1f)
                   1221:                return;         // already hit something nearer
1.1.1.2 ! root     1222: 
1.1       root     1223:        // if < 0, we are in a leaf node
                   1224:        if (num < 0)
                   1225:        {
                   1226:                CM_TraceToLeaf (-1-num);
                   1227:                return;
                   1228:        }
1.1.1.2 ! root     1229: 
1.1       root     1230:        //
                   1231:        // find the point distances to the seperating plane
                   1232:        // and the offset for the size of the box
                   1233:        //
                   1234:        node = map_nodes + num;
                   1235:        plane = node->plane;
1.1.1.2 ! root     1236: 
1.1       root     1237:        if (plane->type < 3)
                   1238:        {
                   1239:                t1 = p1[plane->type] - plane->dist;
                   1240:                t2 = p2[plane->type] - plane->dist;
                   1241:                offset = trace_extents[plane->type];
                   1242:        }
                   1243:        else
                   1244:        {
                   1245:                t1 = DotProduct (plane->normal, p1) - plane->dist;
                   1246:                t2 = DotProduct (plane->normal, p2) - plane->dist;
                   1247:                if (trace_ispoint)
                   1248:                        offset = 0;
                   1249:                else
                   1250:                        offset = fabs(trace_extents[0]*plane->normal[0]) +
                   1251:                                fabs(trace_extents[1]*plane->normal[1]) +
                   1252:                                fabs(trace_extents[2]*plane->normal[2]);
                   1253:        }
1.1.1.2 ! root     1254: 
        !          1255: 
1.1       root     1256: #if 0
                   1257: CM_RecursiveHullCheck (node->children[0], p1f, p2f, p1, p2);
                   1258: CM_RecursiveHullCheck (node->children[1], p1f, p2f, p1, p2);
                   1259: return;
                   1260: #endif
1.1.1.2 ! root     1261: 
1.1       root     1262:        // see which sides we need to consider
                   1263:        if (t1 >= offset && t2 >= offset)
                   1264:        {
                   1265:                CM_RecursiveHullCheck (node->children[0], p1f, p2f, p1, p2);
                   1266:                return;
                   1267:        }
                   1268:        if (t1 < -offset && t2 < -offset)
                   1269:        {
                   1270:                CM_RecursiveHullCheck (node->children[1], p1f, p2f, p1, p2);
                   1271:                return;
                   1272:        }
1.1.1.2 ! root     1273: 
1.1       root     1274:        // put the crosspoint DIST_EPSILON pixels on the near side
                   1275:        if (t1 < t2)
                   1276:        {
                   1277:                idist = 1.0/(t1-t2);
                   1278:                side = 1;
                   1279:                frac2 = (t1 + offset + DIST_EPSILON)*idist;
                   1280:                frac = (t1 - offset + DIST_EPSILON)*idist;
                   1281:        }
                   1282:        else if (t1 > t2)
                   1283:        {
                   1284:                idist = 1.0/(t1-t2);
                   1285:                side = 0;
                   1286:                frac2 = (t1 - offset - DIST_EPSILON)*idist;
                   1287:                frac = (t1 + offset + DIST_EPSILON)*idist;
                   1288:        }
                   1289:        else
                   1290:        {
                   1291:                side = 0;
                   1292:                frac = 1;
                   1293:                frac2 = 0;
                   1294:        }
1.1.1.2 ! root     1295: 
1.1       root     1296:        // move up to the node
                   1297:        if (frac < 0)
                   1298:                frac = 0;
                   1299:        if (frac > 1)
                   1300:                frac = 1;
                   1301:                
                   1302:        midf = p1f + (p2f - p1f)*frac;
                   1303:        for (i=0 ; i<3 ; i++)
                   1304:                mid[i] = p1[i] + frac*(p2[i] - p1[i]);
1.1.1.2 ! root     1305: 
1.1       root     1306:        CM_RecursiveHullCheck (node->children[side], p1f, midf, p1, mid);
1.1.1.2 ! root     1307: 
        !          1308: 
1.1       root     1309:        // go past the node
                   1310:        if (frac2 < 0)
                   1311:                frac2 = 0;
                   1312:        if (frac2 > 1)
                   1313:                frac2 = 1;
                   1314:                
                   1315:        midf = p1f + (p2f - p1f)*frac2;
                   1316:        for (i=0 ; i<3 ; i++)
                   1317:                mid[i] = p1[i] + frac2*(p2[i] - p1[i]);
1.1.1.2 ! root     1318: 
1.1       root     1319:        CM_RecursiveHullCheck (node->children[side^1], midf, p2f, mid, p2);
                   1320: }
1.1.1.2 ! root     1321: 
        !          1322: 
        !          1323: 
1.1       root     1324: //======================================================================
1.1.1.2 ! root     1325: 
1.1       root     1326: /*
                   1327: ==================
                   1328: CM_BoxTrace
                   1329: ==================
                   1330: */
                   1331: trace_t                CM_BoxTrace (vec3_t start, vec3_t end,
                   1332:                                                  vec3_t mins, vec3_t maxs,
                   1333:                                                  int headnode, int brushmask)
                   1334: {
                   1335:        int             i;
1.1.1.2 ! root     1336: 
1.1       root     1337:        checkcount++;           // for multi-check avoidance
1.1.1.2 ! root     1338: 
1.1       root     1339:        c_traces++;                     // for statistics, may be zeroed
1.1.1.2 ! root     1340: 
1.1       root     1341:        // fill in a default trace
                   1342:        memset (&trace_trace, 0, sizeof(trace_trace));
                   1343:        trace_trace.fraction = 1;
1.1.1.2 ! root     1344:        trace_trace.surface = &(nullsurface.c);
1.1       root     1345: 
                   1346:        if (!numnodes)  // map not loaded
                   1347:                return trace_trace;
1.1.1.2 ! root     1348: 
1.1       root     1349:        trace_contents = brushmask;
                   1350:        VectorCopy (start, trace_start);
                   1351:        VectorCopy (end, trace_end);
                   1352:        VectorCopy (mins, trace_mins);
                   1353:        VectorCopy (maxs, trace_maxs);
                   1354: 
                   1355:        //
                   1356:        // check for position test special case
                   1357:        //
                   1358:        if (start[0] == end[0] && start[1] == end[1] && start[2] == end[2])
                   1359:        {
                   1360:                int             leafs[1024];
                   1361:                int             i, numleafs;
                   1362:                vec3_t  c1, c2;
                   1363:                int             topnode;
                   1364: 
                   1365:                VectorAdd (start, mins, c1);
                   1366:                VectorAdd (start, maxs, c2);
                   1367:                for (i=0 ; i<3 ; i++)
                   1368:                {
                   1369:                        c1[i] -= 1;
                   1370:                        c2[i] += 1;
                   1371:                }
                   1372: 
                   1373:                numleafs = CM_BoxLeafnums_headnode (c1, c2, leafs, 1024, headnode, &topnode);
                   1374:                for (i=0 ; i<numleafs ; i++)
                   1375:                {
                   1376:                        CM_TestInLeaf (leafs[i]);
                   1377:                        if (trace_trace.allsolid)
                   1378:                                break;
                   1379:                }
                   1380:                VectorCopy (start, trace_trace.endpos);
                   1381:                return trace_trace;
                   1382:        }
                   1383: 
                   1384:        //
                   1385:        // check for point special case
                   1386:        //
                   1387:        if (mins[0] == 0 && mins[1] == 0 && mins[2] == 0
                   1388:                && maxs[0] == 0 && maxs[1] == 0 && maxs[2] == 0)
                   1389:        {
                   1390:                trace_ispoint = true;
                   1391:                VectorClear (trace_extents);
                   1392:        }
                   1393:        else
                   1394:        {
                   1395:                trace_ispoint = false;
                   1396:                trace_extents[0] = -mins[0] > maxs[0] ? -mins[0] : maxs[0];
                   1397:                trace_extents[1] = -mins[1] > maxs[1] ? -mins[1] : maxs[1];
                   1398:                trace_extents[2] = -mins[2] > maxs[2] ? -mins[2] : maxs[2];
                   1399:        }
                   1400: 
                   1401:        //
                   1402:        // general sweeping through world
                   1403:        //
                   1404:        CM_RecursiveHullCheck (headnode, 0, 1, start, end);
1.1.1.2 ! root     1405: 
1.1       root     1406:        if (trace_trace.fraction == 1)
                   1407:        {
                   1408:                VectorCopy (end, trace_trace.endpos);
                   1409:        }
                   1410:        else
                   1411:        {
                   1412:                for (i=0 ; i<3 ; i++)
                   1413:                        trace_trace.endpos[i] = start[i] + trace_trace.fraction * (end[i] - start[i]);
                   1414:        }
                   1415:        return trace_trace;
                   1416: }
1.1.1.2 ! root     1417: 
        !          1418: 
1.1       root     1419: /*
                   1420: ==================
                   1421: CM_TransformedBoxTrace
1.1.1.2 ! root     1422: 
1.1       root     1423: Handles offseting and rotation of the end points for moving and
                   1424: rotating entities
                   1425: ==================
                   1426: */
                   1427: #ifdef _WIN32
                   1428: #pragma optimize( "", off )
                   1429: #endif
                   1430: 
                   1431: 
                   1432: trace_t                CM_TransformedBoxTrace (vec3_t start, vec3_t end,
                   1433:                                                  vec3_t mins, vec3_t maxs,
                   1434:                                                  int headnode, int brushmask,
                   1435:                                                  vec3_t origin, vec3_t angles)
                   1436: {
                   1437:        trace_t         trace;
                   1438:        vec3_t          start_l, end_l;
                   1439:        vec3_t          a;
                   1440:        vec3_t          forward, right, up;
                   1441:        vec3_t          temp;
                   1442:        qboolean        rotated;
1.1.1.2 ! root     1443: 
1.1       root     1444:        // subtract origin offset
                   1445:        VectorSubtract (start, origin, start_l);
                   1446:        VectorSubtract (end, origin, end_l);
1.1.1.2 ! root     1447: 
1.1       root     1448:        // rotate start and end into the models frame of reference
                   1449:        if (headnode != box_headnode && 
                   1450:        (angles[0] || angles[1] || angles[2]) )
                   1451:                rotated = true;
                   1452:        else
                   1453:                rotated = false;
1.1.1.2 ! root     1454: 
1.1       root     1455:        if (rotated)
                   1456:        {
                   1457:                AngleVectors (angles, forward, right, up);
1.1.1.2 ! root     1458: 
1.1       root     1459:                VectorCopy (start_l, temp);
                   1460:                start_l[0] = DotProduct (temp, forward);
                   1461:                start_l[1] = -DotProduct (temp, right);
                   1462:                start_l[2] = DotProduct (temp, up);
1.1.1.2 ! root     1463: 
1.1       root     1464:                VectorCopy (end_l, temp);
                   1465:                end_l[0] = DotProduct (temp, forward);
                   1466:                end_l[1] = -DotProduct (temp, right);
                   1467:                end_l[2] = DotProduct (temp, up);
                   1468:        }
1.1.1.2 ! root     1469: 
1.1       root     1470:        // sweep the box through the model
                   1471:        trace = CM_BoxTrace (start_l, end_l, mins, maxs, headnode, brushmask);
1.1.1.2 ! root     1472: 
1.1       root     1473:        if (rotated && trace.fraction != 1.0)
                   1474:        {
                   1475:                // FIXME: figure out how to do this with existing angles
                   1476:                VectorNegate (angles, a);
                   1477:                AngleVectors (a, forward, right, up);
1.1.1.2 ! root     1478: 
1.1       root     1479:                VectorCopy (trace.plane.normal, temp);
                   1480:                trace.plane.normal[0] = DotProduct (temp, forward);
                   1481:                trace.plane.normal[1] = -DotProduct (temp, right);
                   1482:                trace.plane.normal[2] = DotProduct (temp, up);
                   1483:        }
1.1.1.2 ! root     1484: 
1.1       root     1485:        trace.endpos[0] = start[0] + trace.fraction * (end[0] - start[0]);
                   1486:        trace.endpos[1] = start[1] + trace.fraction * (end[1] - start[1]);
                   1487:        trace.endpos[2] = start[2] + trace.fraction * (end[2] - start[2]);
1.1.1.2 ! root     1488: 
1.1       root     1489:        return trace;
                   1490: }
1.1.1.2 ! root     1491: 
1.1       root     1492: #ifdef _WIN32
                   1493: #pragma optimize( "", on )
                   1494: #endif
                   1495: 
                   1496: 
1.1.1.2 ! root     1497: 
1.1       root     1498: /*
                   1499: ===============================================================================
1.1.1.2 ! root     1500: 
1.1       root     1501: PVS / PHS
1.1.1.2 ! root     1502: 
1.1       root     1503: ===============================================================================
                   1504: */
1.1.1.2 ! root     1505: 
1.1       root     1506: /*
                   1507: ===================
                   1508: CM_DecompressVis
                   1509: ===================
                   1510: */
                   1511: void CM_DecompressVis (byte *in, byte *out)
                   1512: {
                   1513:        int             c;
                   1514:        byte    *out_p;
                   1515:        int             row;
1.1.1.2 ! root     1516: 
1.1       root     1517:        row = (numclusters+7)>>3;       
                   1518:        out_p = out;
                   1519: 
                   1520:        if (!in || !numvisibility)
                   1521:        {       // no vis info, so make all visible
                   1522:                while (row)
                   1523:                {
                   1524:                        *out_p++ = 0xff;
                   1525:                        row--;
                   1526:                }
                   1527:                return;         
                   1528:        }
1.1.1.2 ! root     1529: 
1.1       root     1530:        do
                   1531:        {
                   1532:                if (*in)
                   1533:                {
                   1534:                        *out_p++ = *in++;
                   1535:                        continue;
                   1536:                }
                   1537:        
                   1538:                c = in[1];
                   1539:                in += 2;
                   1540:                if ((out_p - out) + c > row)
                   1541:                {
                   1542:                        c = row - (out_p - out);
                   1543:                        Com_DPrintf ("warning: Vis decompression overrun\n");
                   1544:                }
                   1545:                while (c)
                   1546:                {
                   1547:                        *out_p++ = 0;
                   1548:                        c--;
                   1549:                }
                   1550:        } while (out_p - out < row);
                   1551: }
1.1.1.2 ! root     1552: 
1.1       root     1553: byte   pvsrow[MAX_MAP_LEAFS/8];
                   1554: byte   phsrow[MAX_MAP_LEAFS/8];
1.1.1.2 ! root     1555: 
1.1       root     1556: byte   *CM_ClusterPVS (int cluster)
                   1557: {
                   1558:        if (cluster == -1)
                   1559:                memset (pvsrow, 0, (numclusters+7)>>3);
                   1560:        else
                   1561:                CM_DecompressVis (map_visibility + map_vis->bitofs[cluster][DVIS_PVS], pvsrow);
                   1562:        return pvsrow;
                   1563: }
1.1.1.2 ! root     1564: 
1.1       root     1565: byte   *CM_ClusterPHS (int cluster)
                   1566: {
                   1567:        if (cluster == -1)
                   1568:                memset (phsrow, 0, (numclusters+7)>>3);
                   1569:        else
                   1570:                CM_DecompressVis (map_visibility + map_vis->bitofs[cluster][DVIS_PHS], phsrow);
                   1571:        return phsrow;
                   1572: }
1.1.1.2 ! root     1573: 
        !          1574: 
1.1       root     1575: /*
                   1576: ===============================================================================
1.1.1.2 ! root     1577: 
1.1       root     1578: AREAPORTALS
1.1.1.2 ! root     1579: 
1.1       root     1580: ===============================================================================
                   1581: */
1.1.1.2 ! root     1582: 
1.1       root     1583: void FloodArea_r (carea_t *area, int floodnum)
                   1584: {
                   1585:        int             i;
                   1586:        dareaportal_t   *p;
1.1.1.2 ! root     1587: 
1.1       root     1588:        if (area->floodvalid == floodvalid)
                   1589:        {
                   1590:                if (area->floodnum == floodnum)
                   1591:                        return;
                   1592:                Com_Error (ERR_DROP, "FloodArea_r: reflooded");
                   1593:        }
1.1.1.2 ! root     1594: 
1.1       root     1595:        area->floodnum = floodnum;
                   1596:        area->floodvalid = floodvalid;
                   1597:        p = &map_areaportals[area->firstareaportal];
                   1598:        for (i=0 ; i<area->numareaportals ; i++, p++)
                   1599:        {
                   1600:                if (portalopen[p->portalnum])
                   1601:                        FloodArea_r (&map_areas[p->otherarea], floodnum);
                   1602:        }
                   1603: }
1.1.1.2 ! root     1604: 
1.1       root     1605: /*
                   1606: ====================
                   1607: FloodAreaConnections
1.1.1.2 ! root     1608: 
        !          1609: 
1.1       root     1610: ====================
                   1611: */
                   1612: void   FloodAreaConnections (void)
                   1613: {
                   1614:        int             i;
                   1615:        carea_t *area;
                   1616:        int             floodnum;
1.1.1.2 ! root     1617: 
1.1       root     1618:        // all current floods are now invalid
                   1619:        floodvalid++;
                   1620:        floodnum = 0;
1.1.1.2 ! root     1621: 
1.1       root     1622:        // area 0 is not used
                   1623:        for (i=1 ; i<numareas ; i++)
                   1624:        {
                   1625:                area = &map_areas[i];
                   1626:                if (area->floodvalid == floodvalid)
                   1627:                        continue;               // already flooded into
                   1628:                floodnum++;
                   1629:                FloodArea_r (area, floodnum);
                   1630:        }
1.1.1.2 ! root     1631: 
1.1       root     1632: }
1.1.1.2 ! root     1633: 
1.1       root     1634: void   CM_SetAreaPortalState (int portalnum, qboolean open)
                   1635: {
                   1636:        if (portalnum > numareaportals)
                   1637:                Com_Error (ERR_DROP, "areaportal > numareaportals");
1.1.1.2 ! root     1638: 
1.1       root     1639:        portalopen[portalnum] = open;
                   1640:        FloodAreaConnections ();
                   1641: }
1.1.1.2 ! root     1642: 
1.1       root     1643: qboolean       CM_AreasConnected (int area1, int area2)
                   1644: {
                   1645:        if (map_noareas->value)
                   1646:                return true;
1.1.1.2 ! root     1647: 
1.1       root     1648:        if (area1 > numareas || area2 > numareas)
                   1649:                Com_Error (ERR_DROP, "area > numareas");
1.1.1.2 ! root     1650: 
1.1       root     1651:        if (map_areas[area1].floodnum == map_areas[area2].floodnum)
                   1652:                return true;
                   1653:        return false;
                   1654: }
1.1.1.2 ! root     1655: 
        !          1656: 
1.1       root     1657: /*
                   1658: =================
                   1659: CM_WriteAreaBits
1.1.1.2 ! root     1660: 
1.1       root     1661: Writes a length byte followed by a bit vector of all the areas
                   1662: that area in the same flood as the area parameter
1.1.1.2 ! root     1663: 
1.1       root     1664: This is used by the client refreshes to cull visibility
                   1665: =================
                   1666: */
                   1667: int CM_WriteAreaBits (byte *buffer, int area)
                   1668: {
                   1669:        int             i;
                   1670:        int             floodnum;
                   1671:        int             bytes;
1.1.1.2 ! root     1672: 
1.1       root     1673:        bytes = (numareas+7)>>3;
1.1.1.2 ! root     1674: 
1.1       root     1675:        if (map_noareas->value)
                   1676:        {       // for debugging, send everything
                   1677:                memset (buffer, 255, bytes);
                   1678:        }
                   1679:        else
                   1680:        {
                   1681:                memset (buffer, 0, bytes);
1.1.1.2 ! root     1682: 
1.1       root     1683:                floodnum = map_areas[area].floodnum;
                   1684:                for (i=0 ; i<numareas ; i++)
                   1685:                {
                   1686:                        if (map_areas[i].floodnum == floodnum || !area)
                   1687:                                buffer[i>>3] |= 1<<(i&7);
                   1688:                }
                   1689:        }
1.1.1.2 ! root     1690: 
1.1       root     1691:        return bytes;
                   1692: }
1.1.1.2 ! root     1693: 
        !          1694: 
1.1       root     1695: /*
                   1696: ===================
                   1697: CM_WritePortalState
1.1.1.2 ! root     1698: 
1.1       root     1699: Writes the portal state to a savegame file
                   1700: ===================
                   1701: */
                   1702: void   CM_WritePortalState (FILE *f)
                   1703: {
                   1704:        fwrite (portalopen, sizeof(portalopen), 1, f);
                   1705: }
1.1.1.2 ! root     1706: 
1.1       root     1707: /*
                   1708: ===================
                   1709: CM_ReadPortalState
1.1.1.2 ! root     1710: 
1.1       root     1711: Reads the portal state from a savegame file
                   1712: and recalculates the area connections
                   1713: ===================
                   1714: */
                   1715: void   CM_ReadPortalState (FILE *f)
                   1716: {
                   1717:        FS_Read (portalopen, sizeof(portalopen), f);
                   1718:        FloodAreaConnections ();
                   1719: }
1.1.1.2 ! root     1720: 
1.1       root     1721: /*
                   1722: =============
                   1723: CM_HeadnodeVisible
1.1.1.2 ! root     1724: 
1.1       root     1725: Returns true if any leaf under headnode has a cluster that
                   1726: is potentially visible
                   1727: =============
                   1728: */
                   1729: qboolean CM_HeadnodeVisible (int nodenum, byte *visbits)
                   1730: {
                   1731:        int             leafnum;
                   1732:        int             cluster;
                   1733:        cnode_t *node;
1.1.1.2 ! root     1734: 
1.1       root     1735:        if (nodenum < 0)
                   1736:        {
                   1737:                leafnum = -1-nodenum;
                   1738:                cluster = map_leafs[leafnum].cluster;
                   1739:                if (cluster == -1)
                   1740:                        return false;
                   1741:                if (visbits[cluster>>3] & (1<<(cluster&7)))
                   1742:                        return true;
                   1743:                return false;
                   1744:        }
1.1.1.2 ! root     1745: 
1.1       root     1746:        node = &map_nodes[nodenum];
                   1747:        if (CM_HeadnodeVisible(node->children[0], visbits))
                   1748:                return true;
                   1749:        return CM_HeadnodeVisible(node->children[1], visbits);
                   1750: }
1.1.1.2 ! root     1751: 

unix.superglobalmegacorp.com

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