Annotation of quake2/ref_soft/r_model.c, revision 1.1

1.1     ! root        1: // models.c -- model loading and caching
        !             2: 
        !             3: // models are the only shared resource between a client and server running
        !             4: // on the same machine.
        !             5: 
        !             6: #include "r_local.h"
        !             7: 
        !             8: model_t        *loadmodel;
        !             9: char   loadname[32];   // for hunk tags
        !            10: 
        !            11: void Mod_LoadSpriteModel (model_t *mod, void *buffer);
        !            12: void Mod_LoadBrushModel (model_t *mod, void *buffer);
        !            13: void Mod_LoadAliasModel (model_t *mod, void *buffer);
        !            14: model_t *Mod_LoadModel (model_t *mod, qboolean crash);
        !            15: 
        !            16: byte   mod_novis[MAX_MAP_LEAFS/8];
        !            17: 
        !            18: #define        MAX_MOD_KNOWN   256
        !            19: model_t        mod_known[MAX_MOD_KNOWN];
        !            20: int            mod_numknown;
        !            21: 
        !            22: // the inline * models from the current map are kept seperate
        !            23: model_t        mod_inline[MAX_MOD_KNOWN];
        !            24: 
        !            25: int            registration_sequence;
        !            26: int            modfilelen;
        !            27: 
        !            28: //===============================================================================
        !            29: 
        !            30: 
        !            31: /*
        !            32: ================
        !            33: Mod_Modellist_f
        !            34: ================
        !            35: */
        !            36: void Mod_Modellist_f (void)
        !            37: {
        !            38:        int             i;
        !            39:        model_t *mod;
        !            40:        int             total;
        !            41: 
        !            42:        total = 0;
        !            43:        ri.Con_Printf (PRINT_ALL,"Loaded models:\n");
        !            44:        for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
        !            45:        {
        !            46:                if (!mod->name[0])
        !            47:                        continue;
        !            48:                ri.Con_Printf (PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name);
        !            49:                total += mod->extradatasize;
        !            50:        }
        !            51:        ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total);
        !            52: }
        !            53: 
        !            54: /*
        !            55: ===============
        !            56: Mod_Init
        !            57: ===============
        !            58: */
        !            59: void Mod_Init (void)
        !            60: {
        !            61:        memset (mod_novis, 0xff, sizeof(mod_novis));
        !            62: }
        !            63: 
        !            64: /*
        !            65: ==================
        !            66: Mod_ForName
        !            67: 
        !            68: Loads in a model for the given name
        !            69: ==================
        !            70: */
        !            71: model_t *Mod_ForName (char *name, qboolean crash)
        !            72: {
        !            73:        model_t *mod;
        !            74:        unsigned *buf;
        !            75:        int             i;
        !            76:        
        !            77:        if (!name[0])
        !            78:                ri.Sys_Error (ERR_DROP,"Mod_ForName: NULL name");
        !            79: 
        !            80:        //
        !            81:        // inline models are grabbed only from worldmodel
        !            82:        //
        !            83:        if (name[0] == '*')
        !            84:        {
        !            85:                i = atoi(name+1);
        !            86:                if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels)
        !            87:                        ri.Sys_Error (ERR_DROP, "bad inline model number");
        !            88:                return &mod_inline[i];
        !            89:        }
        !            90: 
        !            91:        //
        !            92:        // search the currently loaded models
        !            93:        //
        !            94:        for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
        !            95:                if (!strcmp (mod->name, name) )
        !            96:                        return mod;
        !            97:                        
        !            98:        //
        !            99:        // find a free model slot spot
        !           100:        //
        !           101:        for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
        !           102:        {
        !           103:                if (!mod->name[0])
        !           104:                        break;  // free spot
        !           105:        }
        !           106:        if (i == mod_numknown)
        !           107:        {
        !           108:                if (mod_numknown == MAX_MOD_KNOWN)
        !           109:                        ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN");
        !           110:                mod_numknown++;
        !           111:        }
        !           112:        strcpy (mod->name, name);
        !           113:        
        !           114:        //
        !           115:        // load the file
        !           116:        //
        !           117:        modfilelen = ri.FS_LoadFile (mod->name, (void **)&buf);
        !           118:        if (!buf)
        !           119:        {
        !           120:                if (crash)
        !           121:                        ri.Sys_Error (ERR_DROP,"Mod_NumForName: %s not found", mod->name);
        !           122:                memset (mod->name, 0, sizeof(mod->name));
        !           123:                return NULL;
        !           124:        }
        !           125:        
        !           126:        loadmodel = mod;
        !           127: 
        !           128:        //
        !           129:        // fill it in
        !           130:        //
        !           131: 
        !           132:        // call the apropriate loader
        !           133:        
        !           134:        switch (LittleLong(*(unsigned *)buf))
        !           135:        {
        !           136:        case IDALIASHEADER:
        !           137:                loadmodel->extradata = Hunk_Begin (0x200000);
        !           138:                Mod_LoadAliasModel (mod, buf);
        !           139:                break;
        !           140:                
        !           141:        case IDSPRITEHEADER:
        !           142:                loadmodel->extradata = Hunk_Begin (0x10000);
        !           143:                Mod_LoadSpriteModel (mod, buf);
        !           144:                break;
        !           145:        
        !           146:        case IDBSPHEADER:
        !           147:                loadmodel->extradata = Hunk_Begin (0x1000000);
        !           148:                Mod_LoadBrushModel (mod, buf);
        !           149:                break;
        !           150: 
        !           151:        default:
        !           152:                ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name);
        !           153:                break;
        !           154:        }
        !           155: 
        !           156:        loadmodel->extradatasize = Hunk_End ();
        !           157: 
        !           158:        ri.FS_FreeFile (buf);
        !           159: 
        !           160:        return mod;
        !           161: }
        !           162: 
        !           163: 
        !           164: /*
        !           165: ===============
        !           166: Mod_PointInLeaf
        !           167: ===============
        !           168: */
        !           169: mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
        !           170: {
        !           171:        mnode_t         *node;
        !           172:        float           d;
        !           173:        mplane_t        *plane;
        !           174:        
        !           175:        if (!model || !model->nodes)
        !           176:                ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model");
        !           177: 
        !           178:        node = model->nodes;
        !           179:        while (1)
        !           180:        {
        !           181:                if (node->contents != -1)
        !           182:                        return (mleaf_t *)node;
        !           183:                plane = node->plane;
        !           184:                d = DotProduct (p,plane->normal) - plane->dist;
        !           185:                if (d > 0)
        !           186:                        node = node->children[0];
        !           187:                else
        !           188:                        node = node->children[1];
        !           189:        }
        !           190:        
        !           191:        return NULL;    // never reached
        !           192: }
        !           193: 
        !           194: 
        !           195: /*
        !           196: ===================
        !           197: Mod_DecompressVis
        !           198: ===================
        !           199: */
        !           200: byte *Mod_DecompressVis (byte *in, model_t *model)
        !           201: {
        !           202:        static byte     decompressed[MAX_MAP_LEAFS/8];
        !           203:        int             c;
        !           204:        byte    *out;
        !           205:        int             row;
        !           206: 
        !           207:        row = (model->vis->numclusters+7)>>3;   
        !           208:        out = decompressed;
        !           209: 
        !           210: #if 0
        !           211:        memcpy (out, in, row);
        !           212: #else
        !           213:        if (!in)
        !           214:        {       // no vis info, so make all visible
        !           215:                while (row)
        !           216:                {
        !           217:                        *out++ = 0xff;
        !           218:                        row--;
        !           219:                }
        !           220:                return decompressed;            
        !           221:        }
        !           222: 
        !           223:        do
        !           224:        {
        !           225:                if (*in)
        !           226:                {
        !           227:                        *out++ = *in++;
        !           228:                        continue;
        !           229:                }
        !           230:        
        !           231:                c = in[1];
        !           232:                in += 2;
        !           233:                while (c)
        !           234:                {
        !           235:                        *out++ = 0;
        !           236:                        c--;
        !           237:                }
        !           238:        } while (out - decompressed < row);
        !           239: #endif
        !           240:        
        !           241:        return decompressed;
        !           242: }
        !           243: 
        !           244: /*
        !           245: ==============
        !           246: Mod_ClusterPVS
        !           247: ==============
        !           248: */
        !           249: byte *Mod_ClusterPVS (int cluster, model_t *model)
        !           250: {
        !           251:        if (cluster == -1 || !model->vis)
        !           252:                return mod_novis;
        !           253:        return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS],
        !           254:                model);
        !           255: }
        !           256: 
        !           257: /*
        !           258: ===============================================================================
        !           259: 
        !           260:                                        BRUSHMODEL LOADING
        !           261: 
        !           262: ===============================================================================
        !           263: */
        !           264: 
        !           265: byte   *mod_base;
        !           266: 
        !           267: 
        !           268: /*
        !           269: =================
        !           270: Mod_LoadLighting
        !           271: 
        !           272: Converts the 24 bit lighting down to 8 bit
        !           273: by taking the brightest component
        !           274: =================
        !           275: */
        !           276: void Mod_LoadLighting (lump_t *l)
        !           277: {
        !           278:        int             i, size;
        !           279:        byte    *in;
        !           280: 
        !           281:        if (!l->filelen)
        !           282:        {
        !           283:                loadmodel->lightdata = NULL;
        !           284:                return;
        !           285:        }
        !           286:        size = l->filelen/3;
        !           287:        loadmodel->lightdata = Hunk_Alloc (size);
        !           288:        in = (void *)(mod_base + l->fileofs);
        !           289:        for (i=0 ; i<size ; i++, in+=3)
        !           290:        {
        !           291:                if (in[0] > in[1] && in[0] > in[2])
        !           292:                        loadmodel->lightdata[i] = in[0];
        !           293:                else if (in[1] > in[0] && in[1] > in[2])
        !           294:                        loadmodel->lightdata[i] = in[1];
        !           295:                else
        !           296:                        loadmodel->lightdata[i] = in[2];
        !           297:        }
        !           298: }
        !           299: 
        !           300: 
        !           301: int            r_leaftovis[MAX_MAP_LEAFS];
        !           302: int            r_vistoleaf[MAX_MAP_LEAFS];
        !           303: int            r_numvisleafs;
        !           304: 
        !           305: void   R_NumberLeafs (mnode_t *node)
        !           306: {
        !           307:        mleaf_t *leaf;
        !           308:        int             leafnum;
        !           309: 
        !           310:        if (node->contents != -1)
        !           311:        {
        !           312:                leaf = (mleaf_t *)node;
        !           313:                leafnum = leaf - loadmodel->leafs;
        !           314:                if (leaf->contents & CONTENTS_SOLID)
        !           315:                        return;
        !           316:                r_leaftovis[leafnum] = r_numvisleafs;
        !           317:                r_vistoleaf[r_numvisleafs] = leafnum;
        !           318:                r_numvisleafs++;
        !           319:                return;
        !           320:        }
        !           321: 
        !           322:        R_NumberLeafs (node->children[0]);
        !           323:        R_NumberLeafs (node->children[1]);
        !           324: }
        !           325: 
        !           326: 
        !           327: /*
        !           328: =================
        !           329: Mod_LoadVisibility
        !           330: =================
        !           331: */
        !           332: void Mod_LoadVisibility (lump_t *l)
        !           333: {
        !           334:        int             i;
        !           335: 
        !           336:        if (!l->filelen)
        !           337:        {
        !           338:                loadmodel->vis = NULL;
        !           339:                return;
        !           340:        }
        !           341:        loadmodel->vis = Hunk_Alloc ( l->filelen);      
        !           342:        memcpy (loadmodel->vis, mod_base + l->fileofs, l->filelen);
        !           343: 
        !           344:        loadmodel->vis->numclusters = LittleLong (loadmodel->vis->numclusters);
        !           345:        for (i=0 ; i<loadmodel->vis->numclusters ; i++)
        !           346:        {
        !           347:                loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]);
        !           348:                loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]);
        !           349:        }
        !           350: }
        !           351: 
        !           352: 
        !           353: /*
        !           354: =================
        !           355: Mod_LoadVertexes
        !           356: =================
        !           357: */
        !           358: void Mod_LoadVertexes (lump_t *l)
        !           359: {
        !           360:        dvertex_t       *in;
        !           361:        mvertex_t       *out;
        !           362:        int                     i, count;
        !           363: 
        !           364:        in = (void *)(mod_base + l->fileofs);
        !           365:        if (l->filelen % sizeof(*in))
        !           366:                ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        !           367:        count = l->filelen / sizeof(*in);
        !           368:        out = Hunk_Alloc ( (count+8)*sizeof(*out));             // extra for skybox
        !           369: 
        !           370:        loadmodel->vertexes = out;
        !           371:        loadmodel->numvertexes = count;
        !           372: 
        !           373:        for ( i=0 ; i<count ; i++, in++, out++)
        !           374:        {
        !           375:                out->position[0] = LittleFloat (in->point[0]);
        !           376:                out->position[1] = LittleFloat (in->point[1]);
        !           377:                out->position[2] = LittleFloat (in->point[2]);
        !           378:        }
        !           379: }
        !           380: 
        !           381: /*
        !           382: =================
        !           383: Mod_LoadSubmodels
        !           384: =================
        !           385: */
        !           386: void Mod_LoadSubmodels (lump_t *l)
        !           387: {
        !           388:        dmodel_t        *in;
        !           389:        dmodel_t        *out;
        !           390:        int                     i, j, count;
        !           391: 
        !           392:        in = (void *)(mod_base + l->fileofs);
        !           393:        if (l->filelen % sizeof(*in))
        !           394:                ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        !           395:        count = l->filelen / sizeof(*in);
        !           396:        out = Hunk_Alloc ( count*sizeof(*out)); 
        !           397: 
        !           398:        loadmodel->submodels = out;
        !           399:        loadmodel->numsubmodels = count;
        !           400: 
        !           401:        for ( i=0 ; i<count ; i++, in++, out++)
        !           402:        {
        !           403:                for (j=0 ; j<3 ; j++)
        !           404:                {       // spread the mins / maxs by a pixel
        !           405:                        out->mins[j] = LittleFloat (in->mins[j]) - 1;
        !           406:                        out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
        !           407:                        out->origin[j] = LittleFloat (in->origin[j]);
        !           408:                }
        !           409:                out->headnode = LittleLong (in->headnode);
        !           410:                out->firstface = LittleLong (in->firstface);
        !           411:                out->numfaces = LittleLong (in->numfaces);
        !           412:        }
        !           413: }
        !           414: 
        !           415: /*
        !           416: =================
        !           417: Mod_LoadEdges
        !           418: =================
        !           419: */
        !           420: void Mod_LoadEdges (lump_t *l)
        !           421: {
        !           422:        dedge_t *in;
        !           423:        medge_t *out;
        !           424:        int     i, count;
        !           425: 
        !           426:        in = (void *)(mod_base + l->fileofs);
        !           427:        if (l->filelen % sizeof(*in))
        !           428:                ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        !           429:        count = l->filelen / sizeof(*in);
        !           430:        out = Hunk_Alloc ( (count + 13) * sizeof(*out));        // extra for skybox
        !           431: 
        !           432:        loadmodel->edges = out;
        !           433:        loadmodel->numedges = count;
        !           434: 
        !           435:        for ( i=0 ; i<count ; i++, in++, out++)
        !           436:        {
        !           437:                out->v[0] = (unsigned short)LittleShort(in->v[0]);
        !           438:                out->v[1] = (unsigned short)LittleShort(in->v[1]);
        !           439:        }
        !           440: }
        !           441: 
        !           442: /*
        !           443: =================
        !           444: Mod_LoadTexinfo
        !           445: =================
        !           446: */
        !           447: void Mod_LoadTexinfo (lump_t *l)
        !           448: {
        !           449:        texinfo_t *in;
        !           450:        mtexinfo_t *out, *step;
        !           451:        int     i, j, count;
        !           452:        float   len1, len2;
        !           453:        char    name[MAX_QPATH];
        !           454:        int             next;
        !           455: 
        !           456:        in = (void *)(mod_base + l->fileofs);
        !           457:        if (l->filelen % sizeof(*in))
        !           458:                ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        !           459:        count = l->filelen / sizeof(*in);
        !           460:        out = Hunk_Alloc ( (count+6)*sizeof(*out));     // extra for skybox
        !           461: 
        !           462:        loadmodel->texinfo = out;
        !           463:        loadmodel->numtexinfo = count;
        !           464: 
        !           465:        for ( i=0 ; i<count ; i++, in++, out++)
        !           466:        {
        !           467:                for (j=0 ; j<8 ; j++)
        !           468:                        out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
        !           469:                len1 = VectorLength (out->vecs[0]);
        !           470:                len2 = VectorLength (out->vecs[1]);
        !           471:                len1 = (len1 + len2)/2;
        !           472:                if (len1 < 0.32)
        !           473:                        out->mipadjust = 4;
        !           474:                else if (len1 < 0.49)
        !           475:                        out->mipadjust = 3;
        !           476:                else if (len1 < 0.99)
        !           477:                        out->mipadjust = 2;
        !           478:                else
        !           479:                        out->mipadjust = 1;
        !           480: #if 0
        !           481:                if (len1 + len2 < 0.001)
        !           482:                        out->mipadjust = 1;             // don't crash
        !           483:                else
        !           484:                        out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
        !           485: #endif
        !           486: 
        !           487:                out->flags = LittleLong (in->flags);
        !           488: 
        !           489:                next = LittleLong (in->nexttexinfo);
        !           490:                if (next > 0)
        !           491:                        out->next = loadmodel->texinfo + next;
        !           492: 
        !           493:                Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture);
        !           494:                out->image = R_FindImage (name, it_wall);
        !           495:                if (!out->image)
        !           496:                {
        !           497:                        out->image = r_notexture_mip; // texture not found
        !           498:                        out->flags = 0;
        !           499:                }
        !           500:        }
        !           501: 
        !           502:        // count animation frames
        !           503:        for (i=0 ; i<count ; i++)
        !           504:        {
        !           505:                out = &loadmodel->texinfo[i];
        !           506:                out->numframes = 1;
        !           507:                for (step = out->next ; step && step != out ; step=step->next)
        !           508:                        out->numframes++;
        !           509:        }
        !           510: }
        !           511: 
        !           512: /*
        !           513: ================
        !           514: CalcSurfaceExtents
        !           515: 
        !           516: Fills in s->texturemins[] and s->extents[]
        !           517: ================
        !           518: */
        !           519: void CalcSurfaceExtents (msurface_t *s)
        !           520: {
        !           521:        float   mins[2], maxs[2], val;
        !           522:        int             i,j, e;
        !           523:        mvertex_t       *v;
        !           524:        mtexinfo_t      *tex;
        !           525:        int             bmins[2], bmaxs[2];
        !           526: 
        !           527:        mins[0] = mins[1] = 999999;
        !           528:        maxs[0] = maxs[1] = -99999;
        !           529: 
        !           530:        tex = s->texinfo;
        !           531:        
        !           532:        for (i=0 ; i<s->numedges ; i++)
        !           533:        {
        !           534:                e = loadmodel->surfedges[s->firstedge+i];
        !           535:                if (e >= 0)
        !           536:                        v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
        !           537:                else
        !           538:                        v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
        !           539:                
        !           540:                for (j=0 ; j<2 ; j++)
        !           541:                {
        !           542:                        val = v->position[0] * tex->vecs[j][0] + 
        !           543:                                v->position[1] * tex->vecs[j][1] +
        !           544:                                v->position[2] * tex->vecs[j][2] +
        !           545:                                tex->vecs[j][3];
        !           546:                        if (val < mins[j])
        !           547:                                mins[j] = val;
        !           548:                        if (val > maxs[j])
        !           549:                                maxs[j] = val;
        !           550:                }
        !           551:        }
        !           552: 
        !           553:        for (i=0 ; i<2 ; i++)
        !           554:        {       
        !           555:                bmins[i] = floor(mins[i]/16);
        !           556:                bmaxs[i] = ceil(maxs[i]/16);
        !           557: 
        !           558:                s->texturemins[i] = bmins[i] * 16;
        !           559:                s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
        !           560:                if (s->extents[i] < 16)
        !           561:                        s->extents[i] = 16;     // take at least one cache block
        !           562:                if ( !(tex->flags & (SURF_WARP|SURF_SKY)) && s->extents[i] > 256)
        !           563:                        ri.Sys_Error (ERR_DROP,"Bad surface extents");
        !           564:        }
        !           565: }
        !           566: 
        !           567: 
        !           568: /*
        !           569: =================
        !           570: Mod_LoadFaces
        !           571: =================
        !           572: */
        !           573: void Mod_LoadFaces (lump_t *l)
        !           574: {
        !           575:        dface_t         *in;
        !           576:        msurface_t      *out;
        !           577:        int                     i, count, surfnum;
        !           578:        int                     planenum, side;
        !           579: 
        !           580:        in = (void *)(mod_base + l->fileofs);
        !           581:        if (l->filelen % sizeof(*in))
        !           582:                ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        !           583:        count = l->filelen / sizeof(*in);
        !           584:        out = Hunk_Alloc ( (count+6)*sizeof(*out));     // extra for skybox
        !           585: 
        !           586:        loadmodel->surfaces = out;
        !           587:        loadmodel->numsurfaces = count;
        !           588: 
        !           589:        for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
        !           590:        {
        !           591:                out->firstedge = LittleLong(in->firstedge);
        !           592:                out->numedges = LittleShort(in->numedges);              
        !           593:                if (out->numedges < 3)
        !           594:                        ri.Sys_Error (ERR_DROP,"Surface with %s edges", out->numedges);
        !           595:                out->flags = 0;
        !           596: 
        !           597:                planenum = LittleShort(in->planenum);
        !           598:                side = LittleShort(in->side);
        !           599:                if (side)
        !           600:                        out->flags |= SURF_PLANEBACK;                   
        !           601: 
        !           602:                out->plane = loadmodel->planes + planenum;
        !           603: 
        !           604:                out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
        !           605: 
        !           606:                CalcSurfaceExtents (out);
        !           607:                                
        !           608:        // lighting info is converted from 24 bit on disk to 8 bit
        !           609: 
        !           610:                for (i=0 ; i<MAXLIGHTMAPS ; i++)
        !           611:                        out->styles[i] = in->styles[i];
        !           612:                i = LittleLong(in->lightofs);
        !           613:                if (i == -1)
        !           614:                        out->samples = NULL;
        !           615:                else
        !           616:                        out->samples = loadmodel->lightdata + i/3;
        !           617:                
        !           618:        // set the drawing flags flag
        !           619:                
        !           620:                if (!out->texinfo->image)
        !           621:                        continue;
        !           622:                if (out->texinfo->flags & SURF_SKY)
        !           623:                {
        !           624:                        out->flags |= SURF_DRAWSKY;
        !           625:                        continue;
        !           626:                }
        !           627:                
        !           628:                if (out->texinfo->flags & SURF_WARP)
        !           629:                {
        !           630:                        out->flags |= SURF_DRAWTURB;
        !           631:                        for (i=0 ; i<2 ; i++)
        !           632:                        {
        !           633:                                out->extents[i] = 16384;
        !           634:                                out->texturemins[i] = -8192;
        !           635:                        }
        !           636:                        continue;
        !           637:                }
        !           638:        }
        !           639: }
        !           640: 
        !           641: 
        !           642: /*
        !           643: =================
        !           644: Mod_SetParent
        !           645: =================
        !           646: */
        !           647: void Mod_SetParent (mnode_t *node, mnode_t *parent)
        !           648: {
        !           649:        node->parent = parent;
        !           650:        if (node->contents != -1)
        !           651:                return;
        !           652:        Mod_SetParent (node->children[0], node);
        !           653:        Mod_SetParent (node->children[1], node);
        !           654: }
        !           655: 
        !           656: /*
        !           657: =================
        !           658: Mod_LoadNodes
        !           659: =================
        !           660: */
        !           661: void Mod_LoadNodes (lump_t *l)
        !           662: {
        !           663:        int                     i, j, count, p;
        !           664:        dnode_t         *in;
        !           665:        mnode_t         *out;
        !           666: 
        !           667:        in = (void *)(mod_base + l->fileofs);
        !           668:        if (l->filelen % sizeof(*in))
        !           669:                ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        !           670:        count = l->filelen / sizeof(*in);
        !           671:        out = Hunk_Alloc ( count*sizeof(*out)); 
        !           672: 
        !           673:        loadmodel->nodes = out;
        !           674:        loadmodel->numnodes = count;
        !           675: 
        !           676:        for ( i=0 ; i<count ; i++, in++, out++)
        !           677:        {
        !           678:                for (j=0 ; j<3 ; j++)
        !           679:                {
        !           680:                        out->minmaxs[j] = LittleShort (in->mins[j]);
        !           681:                        out->minmaxs[3+j] = LittleShort (in->maxs[j]);
        !           682:                }
        !           683:        
        !           684:                p = LittleLong(in->planenum);
        !           685:                out->plane = loadmodel->planes + p;
        !           686: 
        !           687:                out->firstsurface = LittleShort (in->firstface);
        !           688:                out->numsurfaces = LittleShort (in->numfaces);
        !           689:                out->contents = CONTENTS_NODE;  // differentiate from leafs
        !           690:                
        !           691:                for (j=0 ; j<2 ; j++)
        !           692:                {
        !           693:                        p = LittleLong (in->children[j]);
        !           694:                        if (p >= 0)
        !           695:                                out->children[j] = loadmodel->nodes + p;
        !           696:                        else
        !           697:                                out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
        !           698:                }
        !           699:        }
        !           700:        
        !           701:        Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
        !           702: }
        !           703: 
        !           704: /*
        !           705: =================
        !           706: Mod_LoadLeafs
        !           707: =================
        !           708: */
        !           709: void Mod_LoadLeafs (lump_t *l)
        !           710: {
        !           711:        dleaf_t         *in;
        !           712:        mleaf_t         *out;
        !           713:        int                     i, j, count;
        !           714: 
        !           715:        in = (void *)(mod_base + l->fileofs);
        !           716:        if (l->filelen % sizeof(*in))
        !           717:                ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        !           718:        count = l->filelen / sizeof(*in);
        !           719:        out = Hunk_Alloc ( count*sizeof(*out));
        !           720: 
        !           721:        loadmodel->leafs = out;
        !           722:        loadmodel->numleafs = count;
        !           723: 
        !           724:        for ( i=0 ; i<count ; i++, in++, out++)
        !           725:        {
        !           726:                for (j=0 ; j<3 ; j++)
        !           727:                {
        !           728:                        out->minmaxs[j] = LittleShort (in->mins[j]);
        !           729:                        out->minmaxs[3+j] = LittleShort (in->maxs[j]);
        !           730:                }
        !           731: 
        !           732:                out->contents = LittleLong(in->contents);
        !           733:                out->cluster = LittleShort(in->cluster);
        !           734:                out->area = LittleShort(in->area);
        !           735: 
        !           736:                out->firstmarksurface = loadmodel->marksurfaces +
        !           737:                        LittleShort(in->firstleafface);
        !           738:                out->nummarksurfaces = LittleShort(in->numleaffaces);
        !           739:        }       
        !           740: }
        !           741: 
        !           742: 
        !           743: /*
        !           744: =================
        !           745: Mod_LoadMarksurfaces
        !           746: =================
        !           747: */
        !           748: void Mod_LoadMarksurfaces (lump_t *l)
        !           749: {      
        !           750:        int             i, j, count;
        !           751:        short           *in;
        !           752:        msurface_t **out;
        !           753:        
        !           754:        in = (void *)(mod_base + l->fileofs);
        !           755:        if (l->filelen % sizeof(*in))
        !           756:                ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        !           757:        count = l->filelen / sizeof(*in);
        !           758:        out = Hunk_Alloc ( count*sizeof(*out)); 
        !           759: 
        !           760:        loadmodel->marksurfaces = out;
        !           761:        loadmodel->nummarksurfaces = count;
        !           762: 
        !           763:        for ( i=0 ; i<count ; i++)
        !           764:        {
        !           765:                j = LittleShort(in[i]);
        !           766:                if (j >= loadmodel->numsurfaces)
        !           767:                        ri.Sys_Error (ERR_DROP,"Mod_ParseMarksurfaces: bad surface number");
        !           768:                out[i] = loadmodel->surfaces + j;
        !           769:        }
        !           770: }
        !           771: 
        !           772: /*
        !           773: =================
        !           774: Mod_LoadSurfedges
        !           775: =================
        !           776: */
        !           777: void Mod_LoadSurfedges (lump_t *l)
        !           778: {      
        !           779:        int             i, count;
        !           780:        int             *in, *out;
        !           781:        
        !           782:        in = (void *)(mod_base + l->fileofs);
        !           783:        if (l->filelen % sizeof(*in))
        !           784:                ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        !           785:        count = l->filelen / sizeof(*in);
        !           786:        out = Hunk_Alloc ( (count+24)*sizeof(*out));    // extra for skybox
        !           787: 
        !           788:        loadmodel->surfedges = out;
        !           789:        loadmodel->numsurfedges = count;
        !           790: 
        !           791:        for ( i=0 ; i<count ; i++)
        !           792:                out[i] = LittleLong (in[i]);
        !           793: }
        !           794: 
        !           795: /*
        !           796: =================
        !           797: Mod_LoadPlanes
        !           798: =================
        !           799: */
        !           800: void Mod_LoadPlanes (lump_t *l)
        !           801: {
        !           802:        int                     i, j;
        !           803:        mplane_t        *out;
        !           804:        dplane_t        *in;
        !           805:        int                     count;
        !           806:        int                     bits;
        !           807:        
        !           808:        in = (void *)(mod_base + l->fileofs);
        !           809:        if (l->filelen % sizeof(*in))
        !           810:                ri.Sys_Error (ERR_DROP,"MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
        !           811:        count = l->filelen / sizeof(*in);
        !           812:        out = Hunk_Alloc ( (count+6)*sizeof(*out));             // extra for skybox
        !           813:        
        !           814:        loadmodel->planes = out;
        !           815:        loadmodel->numplanes = count;
        !           816: 
        !           817:        for ( i=0 ; i<count ; i++, in++, out++)
        !           818:        {
        !           819:                bits = 0;
        !           820:                for (j=0 ; j<3 ; j++)
        !           821:                {
        !           822:                        out->normal[j] = LittleFloat (in->normal[j]);
        !           823:                        if (out->normal[j] < 0)
        !           824:                                bits |= 1<<j;
        !           825:                }
        !           826: 
        !           827:                out->dist = LittleFloat (in->dist);
        !           828:                out->type = LittleLong (in->type);
        !           829:                out->signbits = bits;
        !           830:        }
        !           831: }
        !           832: 
        !           833: 
        !           834: /*
        !           835: =================
        !           836: Mod_LoadBrushModel
        !           837: =================
        !           838: */
        !           839: void Mod_LoadBrushModel (model_t *mod, void *buffer)
        !           840: {
        !           841:        int                     i;
        !           842:        dheader_t       *header;
        !           843:        dmodel_t        *bm;
        !           844:        
        !           845:        loadmodel->type = mod_brush;
        !           846:        if (loadmodel != mod_known)
        !           847:                ri.Sys_Error (ERR_DROP, "Loaded a brush model after the world");
        !           848:        
        !           849:        header = (dheader_t *)buffer;
        !           850: 
        !           851:        i = LittleLong (header->version);
        !           852:        if (i != BSPVERSION)
        !           853:                ri.Sys_Error (ERR_DROP,"Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
        !           854: 
        !           855: // swap all the lumps
        !           856:        mod_base = (byte *)header;
        !           857: 
        !           858:        for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
        !           859:                ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
        !           860: 
        !           861: // load into heap
        !           862:        
        !           863:        Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
        !           864:        Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
        !           865:        Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
        !           866:        Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
        !           867:        Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
        !           868:        Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
        !           869:        Mod_LoadFaces (&header->lumps[LUMP_FACES]);
        !           870:        Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]);
        !           871:        Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
        !           872:        Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
        !           873:        Mod_LoadNodes (&header->lumps[LUMP_NODES]);
        !           874:        Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
        !           875:        r_numvisleafs = 0;
        !           876:        R_NumberLeafs (loadmodel->nodes);
        !           877:        
        !           878: //
        !           879: // set up the submodels
        !           880: //
        !           881:        for (i=0 ; i<mod->numsubmodels ; i++)
        !           882:        {
        !           883:                model_t *starmod;
        !           884: 
        !           885:                bm = &mod->submodels[i];
        !           886:                starmod = &mod_inline[i];
        !           887: 
        !           888:                *starmod = *loadmodel;
        !           889:                
        !           890:                starmod->firstmodelsurface = bm->firstface;
        !           891:                starmod->nummodelsurfaces = bm->numfaces;
        !           892:                starmod->firstnode = bm->headnode;
        !           893:                if (starmod->firstnode >= loadmodel->numnodes)
        !           894:                        ri.Sys_Error (ERR_DROP, "Inline model %i has bad firstnode", i);
        !           895: 
        !           896:                VectorCopy (bm->maxs, starmod->maxs);
        !           897:                VectorCopy (bm->mins, starmod->mins);
        !           898:        
        !           899:                if (i == 0)
        !           900:                        *loadmodel = *starmod;
        !           901:        }
        !           902: 
        !           903:        R_InitSkyBox ();
        !           904: }
        !           905: 
        !           906: /*
        !           907: ==============================================================================
        !           908: 
        !           909: ALIAS MODELS
        !           910: 
        !           911: ==============================================================================
        !           912: */
        !           913: 
        !           914: /*
        !           915: =================
        !           916: Mod_LoadAliasModel
        !           917: =================
        !           918: */
        !           919: void Mod_LoadAliasModel (model_t *mod, void *buffer)
        !           920: {
        !           921:        int                                     i, j;
        !           922:        dmdl_t                          *pinmodel, *pheader;
        !           923:        dstvert_t                       *pinst, *poutst;
        !           924:        dtriangle_t                     *pintri, *pouttri;
        !           925:        daliasframe_t           *pinframe, *poutframe;
        !           926:        int                                     *pincmd, *poutcmd;
        !           927:        int                                     version;
        !           928: 
        !           929:        pinmodel = (dmdl_t *)buffer;
        !           930: 
        !           931:        version = LittleLong (pinmodel->version);
        !           932:        if (version != ALIAS_VERSION)
        !           933:                ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
        !           934:                                 mod->name, version, ALIAS_VERSION);
        !           935: 
        !           936:        pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end));
        !           937:        
        !           938:        // byte swap the header fields and sanity check
        !           939:        for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
        !           940:                ((int *)pheader)[i] = LittleLong (((int *)buffer)[i]);
        !           941: 
        !           942:        if (pheader->skinheight > MAX_LBM_HEIGHT)
        !           943:                ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name,
        !           944:                                   MAX_LBM_HEIGHT);
        !           945: 
        !           946:        if (pheader->num_xyz <= 0)
        !           947:                ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name);
        !           948: 
        !           949:        if (pheader->num_xyz > MAX_VERTS)
        !           950:                ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name);
        !           951: 
        !           952:        if (pheader->num_st <= 0)
        !           953:                ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name);
        !           954: 
        !           955:        if (pheader->num_tris <= 0)
        !           956:                ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name);
        !           957: 
        !           958:        if (pheader->num_frames <= 0)
        !           959:                ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name);
        !           960: 
        !           961: //
        !           962: // load base s and t vertices (not used in gl version)
        !           963: //
        !           964:        pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st);
        !           965:        poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st);
        !           966: 
        !           967:        for (i=0 ; i<pheader->num_st ; i++)
        !           968:        {
        !           969:                poutst[i].s = LittleShort (pinst[i].s);
        !           970:                poutst[i].t = LittleShort (pinst[i].t);
        !           971:        }
        !           972: 
        !           973: //
        !           974: // load triangle lists
        !           975: //
        !           976:        pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris);
        !           977:        pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);
        !           978: 
        !           979:        for (i=0 ; i<pheader->num_tris ; i++)
        !           980:        {
        !           981:                for (j=0 ; j<3 ; j++)
        !           982:                {
        !           983:                        pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]);
        !           984:                        pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]);
        !           985:                }
        !           986:        }
        !           987: 
        !           988: //
        !           989: // load the frames
        !           990: //
        !           991:        for (i=0 ; i<pheader->num_frames ; i++)
        !           992:        {
        !           993:                pinframe = (daliasframe_t *) ((byte *)pinmodel 
        !           994:                        + pheader->ofs_frames + i * pheader->framesize);
        !           995:                poutframe = (daliasframe_t *) ((byte *)pheader 
        !           996:                        + pheader->ofs_frames + i * pheader->framesize);
        !           997: 
        !           998:                memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name));
        !           999:                for (j=0 ; j<3 ; j++)
        !          1000:                {
        !          1001:                        poutframe->scale[j] = LittleFloat (pinframe->scale[j]);
        !          1002:                        poutframe->translate[j] = LittleFloat (pinframe->translate[j]);
        !          1003:                }
        !          1004:                // verts are all 8 bit, so no swapping needed
        !          1005:                memcpy (poutframe->verts, pinframe->verts, 
        !          1006:                        pheader->num_xyz*sizeof(dtrivertx_t));
        !          1007: 
        !          1008:        }
        !          1009: 
        !          1010:        mod->type = mod_alias;
        !          1011: 
        !          1012:        //
        !          1013:        // load the glcmds
        !          1014:        //
        !          1015:        pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds);
        !          1016:        poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds);
        !          1017:        for (i=0 ; i<pheader->num_glcmds ; i++)
        !          1018:                poutcmd[i] = LittleLong (pincmd[i]);
        !          1019: 
        !          1020: 
        !          1021:        // register all skins
        !          1022:        memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins,
        !          1023:                pheader->num_skins*MAX_SKINNAME);
        !          1024:        for (i=0 ; i<pheader->num_skins ; i++)
        !          1025:        {
        !          1026:                mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
        !          1027:        }
        !          1028: }
        !          1029: 
        !          1030: /*
        !          1031: ==============================================================================
        !          1032: 
        !          1033: SPRITE MODELS
        !          1034: 
        !          1035: ==============================================================================
        !          1036: */
        !          1037: 
        !          1038: /*
        !          1039: =================
        !          1040: Mod_LoadSpriteModel
        !          1041: =================
        !          1042: */
        !          1043: void Mod_LoadSpriteModel (model_t *mod, void *buffer)
        !          1044: {
        !          1045:        dsprite_t       *sprin, *sprout;
        !          1046:        int                     i;
        !          1047: 
        !          1048:        sprin = (dsprite_t *)buffer;
        !          1049:        sprout = Hunk_Alloc (modfilelen);
        !          1050: 
        !          1051:        sprout->ident = LittleLong (sprin->ident);
        !          1052:        sprout->version = LittleLong (sprin->version);
        !          1053:        sprout->numframes = LittleLong (sprin->numframes);
        !          1054: 
        !          1055:        if (sprout->version != SPRITE_VERSION)
        !          1056:                ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
        !          1057:                                 mod->name, sprout->version, SPRITE_VERSION);
        !          1058: 
        !          1059:        if (sprout->numframes > MAX_MD2SKINS)
        !          1060:                ri.Sys_Error (ERR_DROP, "%s has too many frames (%i > %i)",
        !          1061:                                 mod->name, sprout->numframes, MAX_MD2SKINS);
        !          1062: 
        !          1063:        // byte swap everything
        !          1064:        for (i=0 ; i<sprout->numframes ; i++)
        !          1065:        {
        !          1066:                sprout->frames[i].width = LittleLong (sprin->frames[i].width);
        !          1067:                sprout->frames[i].height = LittleLong (sprin->frames[i].height);
        !          1068:                sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x);
        !          1069:                sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y);
        !          1070:                memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME);
        !          1071:                mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite);
        !          1072:        }
        !          1073: 
        !          1074:        mod->type = mod_sprite;
        !          1075: }
        !          1076: 
        !          1077: //=============================================================================
        !          1078: 
        !          1079: /*
        !          1080: @@@@@@@@@@@@@@@@@@@@@
        !          1081: R_BeginRegistration
        !          1082: 
        !          1083: Specifies the model that will be used as the world
        !          1084: @@@@@@@@@@@@@@@@@@@@@
        !          1085: */
        !          1086: void R_BeginRegistration (char *model)
        !          1087: {
        !          1088:        char    fullname[MAX_QPATH];
        !          1089:        cvar_t  *flushmap;
        !          1090: 
        !          1091:        registration_sequence++;
        !          1092:        r_oldviewcluster = -1;          // force markleafs
        !          1093:        Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model);
        !          1094: 
        !          1095:        D_FlushCaches ();
        !          1096:        // explicitly free the old map if different
        !          1097:        // this guarantees that mod_known[0] is the world map
        !          1098:        flushmap = ri.Cvar_Get ("flushmap", "0", 0);
        !          1099:        if ( strcmp(mod_known[0].name, fullname) || flushmap->value)
        !          1100:                Mod_Free (&mod_known[0]);
        !          1101:        r_worldmodel = R_RegisterModel (fullname);
        !          1102:        R_NewMap ();
        !          1103: }
        !          1104: 
        !          1105: 
        !          1106: /*
        !          1107: @@@@@@@@@@@@@@@@@@@@@
        !          1108: R_RegisterModel
        !          1109: 
        !          1110: @@@@@@@@@@@@@@@@@@@@@
        !          1111: */
        !          1112: struct model_s *R_RegisterModel (char *name)
        !          1113: {
        !          1114:        model_t *mod;
        !          1115:        int             i;
        !          1116:        dsprite_t       *sprout;
        !          1117:        dmdl_t          *pheader;
        !          1118: 
        !          1119:        mod = Mod_ForName (name, false);
        !          1120:        if (mod)
        !          1121:        {
        !          1122:                mod->registration_sequence = registration_sequence;
        !          1123: 
        !          1124:                // register any images used by the models
        !          1125:                if (mod->type == mod_sprite)
        !          1126:                {
        !          1127:                        sprout = (dsprite_t *)mod->extradata;
        !          1128:                        for (i=0 ; i<sprout->numframes ; i++)
        !          1129:                                mod->skins[i] = R_FindImage (sprout->frames[i].name, it_sprite);
        !          1130:                }
        !          1131:                else if (mod->type == mod_alias)
        !          1132:                {
        !          1133:                        pheader = (dmdl_t *)mod->extradata;
        !          1134:                        for (i=0 ; i<pheader->num_skins ; i++)
        !          1135:                                mod->skins[i] = R_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
        !          1136:                }
        !          1137:                else if (mod->type == mod_brush)
        !          1138:                {
        !          1139:                        for (i=0 ; i<mod->numtexinfo ; i++)
        !          1140:                                mod->texinfo[i].image->registration_sequence = registration_sequence;
        !          1141:                }
        !          1142:        }
        !          1143:        return mod;
        !          1144: }
        !          1145: 
        !          1146: /*
        !          1147: @@@@@@@@@@@@@@@@@@@@@
        !          1148: R_EndRegistration
        !          1149: 
        !          1150: @@@@@@@@@@@@@@@@@@@@@
        !          1151: */
        !          1152: void R_EndRegistration (void)
        !          1153: {
        !          1154:        int             i;
        !          1155:        model_t *mod;
        !          1156: 
        !          1157:        for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++)
        !          1158:        {
        !          1159:                if (!mod->name[0])
        !          1160:                        continue;
        !          1161:                if (mod->registration_sequence != registration_sequence)
        !          1162:                {       // don't need this model
        !          1163:                        Hunk_Free (mod->extradata);
        !          1164:                        memset (mod, 0, sizeof(*mod));
        !          1165:                }
        !          1166:                else
        !          1167:                {       // make sure it is paged in
        !          1168:                        Com_PageInMemory (mod->extradata, mod->extradatasize);
        !          1169:                }
        !          1170:        }
        !          1171: 
        !          1172:        R_FreeUnusedImages ();
        !          1173: }
        !          1174: 
        !          1175: 
        !          1176: //=============================================================================
        !          1177: 
        !          1178: /*
        !          1179: ================
        !          1180: Mod_Free
        !          1181: ================
        !          1182: */
        !          1183: void Mod_Free (model_t *mod)
        !          1184: {
        !          1185:        Hunk_Free (mod->extradata);
        !          1186:        memset (mod, 0, sizeof(*mod));
        !          1187: }
        !          1188: 
        !          1189: /*
        !          1190: ================
        !          1191: Mod_FreeAll
        !          1192: ================
        !          1193: */
        !          1194: void Mod_FreeAll (void)
        !          1195: {
        !          1196:        int             i;
        !          1197: 
        !          1198:        for (i=0 ; i<mod_numknown ; i++)
        !          1199:        {
        !          1200:                if (mod_known[i].extradatasize)
        !          1201:                        Mod_Free (&mod_known[i]);
        !          1202:        }
        !          1203: }

unix.superglobalmegacorp.com

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