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

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

unix.superglobalmegacorp.com

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