Annotation of quake2/ref_soft/r_model.c, revision 1.1.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.