r_model.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 1997-2001 Id Software, Inc.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "r_local.h"
00027 
00028 model_t r_models[MAX_MOD_KNOWN];
00029 int r_numModels;
00030 static int r_numModelsStatic;
00031 
00032 model_t *r_mapTiles[MAX_MAPTILES];
00033 int r_numMapTiles;
00034 
00035 /* the inline * models from the current map are kept seperate */
00036 model_t r_modelsInline[MAX_MOD_KNOWN];
00037 int r_numModelsInline;
00038 
00042 void R_ModModellist_f (void)
00043 {
00044     int i;
00045     model_t *mod;
00046 
00047     Com_Printf("Loaded models:\n");
00048     Com_Printf("Type | #Slot | #Tris   | #Meshes | Filename\n");
00049     for (i = 0, mod = r_models; i < r_numModels; i++, mod++) {
00050         if (!mod->name[0]) {
00051             Com_Printf("Empty slot %i\n", i);
00052             continue;
00053         }
00054         switch(mod->type) {
00055         case mod_alias_md3:
00056             Com_Printf("MD3 ");
00057             break;
00058         case mod_alias_md2:
00059             Com_Printf("MD2 ");
00060             break;
00061         case mod_alias_dpm:
00062             Com_Printf("DPM ");
00063             break;
00064         case mod_bsp:
00065             Com_Printf("BSP ");
00066             break;
00067         case mod_bsp_submodel:
00068             Com_Printf("SUB ");
00069             break;
00070         case mod_obj:
00071             Com_Printf("OBJ ");
00072             break;
00073         default:
00074             Com_Printf("%3i ", mod->type);
00075             break;
00076         }
00077         if (mod->alias.num_meshes) {
00078             int j;
00079             Com_Printf(" | %5i | %7i | %7i | %s (skins: %i)\n", i, mod->alias.num_meshes, mod->alias.meshes[0].num_tris, mod->name, mod->alias.meshes[0].num_skins);
00080             for (j = 0; j < mod->alias.meshes[0].num_skins; j++) {
00081                 mAliasSkin_t *skin = &mod->alias.meshes[0].skins[j];
00082                 Com_Printf("     \\-- skin %i: '%s' (texnum %i and image type %i)\n", j + 1, skin->name, skin->skin->texnum, skin->skin->type);
00083             }
00084         } else
00085             Com_Printf(" | %5i | %7i | unknown | %s\n", i, mod->alias.num_meshes, mod->name);
00086     }
00087     Com_Printf("%4i models loaded\n", r_numModels);
00088     Com_Printf(" - %4i static models\n", r_numModelsStatic);
00089     Com_Printf(" - %4i bsp models\n", r_numMapTiles);
00090     Com_Printf(" - %4i inline models\n", r_numModelsInline);
00091 }
00092 
00097 static model_t *R_ModForName (const char *name, qboolean crash)
00098 {
00099     model_t *mod;
00100     byte *buf;
00101     int i;
00102     int modfilelen;
00103 
00104     if (name[0] == '\0')
00105         Com_Error(ERR_FATAL, "R_ModForName: NULL name");
00106 
00107     /* inline models are grabbed only from worldmodel */
00108     if (name[0] == '*') {
00109         i = atoi(name + 1) - 1;
00110         if (i < 0 || i >= r_numModelsInline)
00111             Com_Error(ERR_FATAL, "bad inline model number '%s' (%i/%i)", name, i, r_numModelsInline);
00112         return &r_modelsInline[i];
00113     }
00114 
00115     /* search the currently loaded models */
00116     for (i = 0, mod = r_models; i < r_numModels; i++, mod++)
00117         if (!strcmp(mod->name, name))
00118             return mod;
00119 
00120     /* find a free model slot spot */
00121     for (i = 0, mod = r_models; i < r_numModels; i++, mod++) {
00122         if (!mod->name[0])
00123             break;              /* free spot */
00124     }
00125 
00126     if (i == r_numModels) {
00127         if (r_numModels == MAX_MOD_KNOWN)
00128             Com_Error(ERR_FATAL, "r_numModels == MAX_MOD_KNOWN");
00129         r_numModels++;
00130     }
00131 
00132     memset(mod, 0, sizeof(*mod));
00133     Q_strncpyz(mod->name, name, sizeof(mod->name));
00134 
00135     /* load the file */
00136     modfilelen = FS_LoadFile(mod->name, &buf);
00137     if (!buf) {
00138         if (crash)
00139             Com_Error(ERR_FATAL, "R_ModForName: %s not found", mod->name);
00140         memset(mod->name, 0, sizeof(mod->name));
00141         r_numModels--;
00142         return NULL;
00143     }
00144 
00145     /* call the appropriate loader */
00146     switch (LittleLong(*(unsigned *) buf)) {
00147     case IDALIASHEADER:
00148         /* MD2 header */
00149         R_ModLoadAliasMD2Model(mod, buf, modfilelen, qtrue);
00150         break;
00151 
00152     case DPMHEADER:
00153         R_ModLoadAliasDPMModel(mod, buf, modfilelen);
00154         break;
00155 
00156     case IDMD3HEADER:
00157         /* MD3 header */
00158         R_ModLoadAliasMD3Model(mod, buf, modfilelen);
00159         break;
00160 
00161     case IDBSPHEADER:
00162         Com_Error(ERR_FATAL, "R_ModForName: don't load BSPs with this function");
00163         break;
00164 
00165     default:
00166         if (!Q_strcasecmp(mod->name + strlen(mod->name) - 4, ".obj"))
00167             R_LoadObjModel(mod, buf, modfilelen);
00168         else
00169             Com_Error(ERR_FATAL, "R_ModForName: unknown fileid for %s", mod->name);
00170     }
00171 
00172     FS_FreeFile(buf);
00173 
00174     return mod;
00175 }
00176 
00181 static const char *mod_extensions[] = {
00182     "md2", "md3", "dpm", "obj", NULL
00183 };
00184 
00197 model_t *R_RegisterModelShort (const char *name)
00198 {
00199     model_t *mod;
00200 
00201     if (!name || !name[0])
00202         return NULL;
00203 
00204     if (name[0] != '*' && (strlen(name) < 4 || name[strlen(name) - 4] != '.')) {
00205         char filename[MAX_QPATH];
00206         int i = 0;
00207 
00208         while (mod_extensions[i]) {
00209             Com_sprintf(filename, sizeof(filename), "models/%s.%s", name, mod_extensions[i]);
00210             mod = R_ModForName(filename, qfalse);
00211             if (mod)
00212                 return mod;
00213             i++;
00214         }
00215         Com_Printf("R_RegisterModelShort: Could not find: '%s'\n", name);
00216         return NULL;
00217     } else
00218         return R_ModForName(name, qfalse);
00219 }
00220 
00221 #define MEM_TAG_STATIC_MODELS 1
00222 
00228 void R_SwitchModelMemPoolTag (void)
00229 {
00230     int i, j, k;
00231     model_t* mod;
00232 
00233     r_numModelsStatic = r_numModels;
00234     Mem_ChangeTag(vid_modelPool, 0, MEM_TAG_STATIC_MODELS);
00235 
00236     /* mark the static model textures as it_static, thus R_FreeWorldImages
00237      * won't free them */
00238     for (i = 0, mod = r_models; i < r_numModelsStatic; i++, mod++) {
00239         if (!mod->alias.num_meshes)
00240             Com_Printf("Model '%s' has no meshes\n", mod->name);
00241         for (j = 0; j < mod->alias.num_meshes; j++) {
00242             if (!mod->alias.meshes[j].num_skins)
00243                 Com_Printf("Model '%s' has no skins\n", mod->name);
00244             for (k = 0; k < mod->alias.meshes[j].num_skins; k++) {
00245                 if (mod->alias.meshes[j].skins[k].skin != r_noTexture)
00246                     mod->alias.meshes[j].skins[k].skin->type = it_static;
00247                 else
00248                     Com_Printf("No skin for #%i of '%s'\n", j, mod->name);
00249             }
00250         }
00251     }
00252 
00253     Com_Printf("%i static models loaded\n", r_numModels);
00254 }
00255 
00261 void R_ShutdownModels (qboolean complete)
00262 {
00263     int i;
00264     const int start = complete ? 0 : r_numModelsStatic;
00265 
00266     /* free the vertex buffer - but not for the static models
00267      * the world, the submodels and all the misc_models are located in the
00268      * r_models array */
00269     for (i = start; i < r_numModels; i++) {
00270         model_t *mod = &r_models[i];
00271 
00272         if (mod->bsp.vertex_buffer)
00273             qglDeleteBuffers(1, &mod->bsp.vertex_buffer);
00274         if (mod->bsp.texcoord_buffer)
00275             qglDeleteBuffers(1, &mod->bsp.texcoord_buffer);
00276         if (mod->bsp.lmtexcoord_buffer)
00277             qglDeleteBuffers(1, &mod->bsp.lmtexcoord_buffer);
00278         if (mod->bsp.normal_buffer)
00279             qglDeleteBuffers(1, &mod->bsp.normal_buffer);
00280         if (mod->bsp.tangent_buffer)
00281             qglDeleteBuffers(1, &mod->bsp.tangent_buffer);
00282     }
00283 
00284     /* don't free the static models with the tag MEM_TAG_STATIC_MODELS */
00285     if (complete) {
00286         if (vid_modelPool)
00287             Mem_FreePool(vid_modelPool);
00288         if (vid_lightPool)
00289             Mem_FreePool(vid_lightPool);
00290         r_numModels = 0;
00291         memset(&r_models, 0, sizeof(r_models));
00292     } else {
00293         if (vid_modelPool)
00294             Mem_FreeTag(vid_modelPool, 0);
00295         if (vid_lightPool)
00296             Mem_FreeTag(vid_lightPool, 0);
00297         r_numModels = r_numModelsStatic;
00298     }
00299 }

Generated by  doxygen 1.6.2