00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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
00116 for (i = 0, mod = r_models; i < r_numModels; i++, mod++)
00117 if (!strcmp(mod->name, name))
00118 return mod;
00119
00120
00121 for (i = 0, mod = r_models; i < r_numModels; i++, mod++) {
00122 if (!mod->name[0])
00123 break;
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
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
00146 switch (LittleLong(*(unsigned *) buf)) {
00147 case IDALIASHEADER:
00148
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
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
00237
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
00267
00268
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
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 }