UFO: Alien Invasion
Loading...
Searching...
No Matches
r_model.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 1997-2001 Id Software, Inc.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
24*/
25
26#include "r_local.h"
27
29static int r_numModels;
31
32model_t* r_mapTiles[MAX_MAPTILES];
34
35/* the inline * models from the current map are kept separate */
38
41
46static char const* const mod_extensions[] = {
47 "md2", "md3", "obj", nullptr
48};
49
54{
55 int i;
56 model_t* mod;
57
58 Com_Printf("Loaded models:\n");
59 Com_Printf("Type | #Slot | #Tris | #Meshes | Filename\n");
60 for (i = 0, mod = r_models; i < r_numModels; i++, mod++) {
61 if (!mod->name[0]) {
62 Com_Printf("Empty slot %i\n", i);
63 continue;
64 }
65 switch(mod->type) {
66 case mod_alias_md3:
67 Com_Printf("MD3 ");
68 break;
69 case mod_alias_md2:
70 Com_Printf("MD2 ");
71 break;
72 case mod_bsp:
73 Com_Printf("BSP ");
74 break;
76 Com_Printf("SUB ");
77 break;
78 case mod_obj:
79 Com_Printf("OBJ ");
80 break;
81 default:
82 Com_Printf("%3i ", mod->type);
83 break;
84 }
85 if (mod->alias.num_meshes) {
86 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);
87 for (int j = 0; j < mod->alias.meshes[0].num_skins; j++) {
88 mAliasSkin_t* skin = &mod->alias.meshes[0].skins[j];
89 Com_Printf(" \\-- skin %i: '%s' (texnum %i and image type %i)\n", j + 1, skin->name, skin->skin->texnum, skin->skin->type);
90 }
91 } else
92 Com_Printf(" | %5i | %7i | unknown | %s\n", i, mod->alias.num_meshes, mod->name);
93 }
94 Com_Printf("%4i models loaded\n", r_numModels);
95 Com_Printf(" - %4i static models\n", r_numModelsStatic);
96 Com_Printf(" - %4i bsp models\n", r_numMapTiles);
97 Com_Printf(" - %4i inline models\n", r_numModelsInline);
98}
99
101{
102 /* get new model */
104 Com_Error(ERR_DROP, "R_ModAddMapTile: r_numModels >= MAX_MOD_KNOWN");
105 return &r_models[r_numModels++];
106}
107
108static void R_LoadModelAsync (model_t* mod, byte* buf, int modfilelen)
109{
110 /* call the appropriate loader */
111 switch (LittleLong(*(unsigned* ) buf)) {
112 case IDALIASHEADER:
113 /* MD2 header */
114 R_ModLoadAliasMD2Model(mod, buf, modfilelen, true);
115 break;
116
117 case IDMD3HEADER:
118 /* MD3 header */
119 R_ModLoadAliasMD3Model(mod, buf, modfilelen);
120 break;
121
122 case IDBSPHEADER:
123 Com_Error(ERR_FATAL, "R_ModForName: don't load BSPs with this function");
124 break;
125
126 default:
127 {
128 const char* ext = Com_GetExtension(mod->name);
129 if (ext != nullptr && !Q_strcasecmp(ext, "obj"))
130 R_LoadObjModel(mod, buf, modfilelen);
131 else
132 Com_Error(ERR_FATAL, "R_ModForName: unknown fileid for %s", mod->name);
133 }
134 }
135
136 /* load the animations */
137 char animname[MAX_QPATH];
138 Com_StripExtension(mod->name, animname, sizeof(animname));
139 Com_DefaultExtension(animname, sizeof(animname), ".anm");
140
141 /* try to load the animation file */
142 if (FS_CheckFile("%s", animname) != -1) {
143 R_ModLoadAnims(&mod->alias, animname);
144 }
145
147
148 mod->loaded = true;
149}
150
157static bool R_LoadModel (model_t* mod, const char* filename)
158{
159 byte* buf;
160 int modfilelen;
161
162 if (filename[0] == '\0')
163 Com_Error(ERR_FATAL, "R_ModForName: nullptr name");
164
165 /* load the file */
166 modfilelen = FS_LoadFile(filename, &buf);
167 if (!buf)
168 return false;
169
170 OBJZERO(*mod);
171 Q_strncpyz(mod->name, filename, sizeof(mod->name));
172
173 R_LoadModelAsync(mod, buf, modfilelen);
174 return true;
175}
176
177bool R_ModelExists (const char* name)
178{
179 if (Com_GetExtension(name) == nullptr) {
180 for (int i = 0; mod_extensions[i] != nullptr; i++) {
181 if (FS_CheckFile("models/%s.%s", name, mod_extensions[i]) != -1) {
182 return true;
183 }
184 }
185 return false;
186 }
187
188 return FS_CheckFile("models/%s", name) != -1;
189}
190
204{
205 model_t* mod;
206 model_t model;
207 bool loaded = false;
208 int i;
209
210 if (!name || !name[0])
211 return nullptr;
212
213 /* search for existing models */
214 mod = R_GetModel(name);
215 if (mod != nullptr)
216 return mod;
217
218 /* no inline bsp models here */
219 if (name[0] == '*')
220 return nullptr;
221
222 /* load model */
223 if (Com_GetExtension(name) == nullptr) {
224 char filename[MAX_QPATH];
225
226 for (i = 0; mod_extensions[i] != nullptr; i++) {
227 Com_sprintf(filename, sizeof(filename), "models/%s.%s", name, mod_extensions[i]);
228 loaded = R_LoadModel(&model, filename);
229 if (loaded) {
230 /* use short name */
231 Q_strncpyz(model.name, name, sizeof(model.name));
232 break;
233 }
234 }
235 } else {
237 loaded = R_LoadModel(&model, name);
238 }
239
240 if (!loaded) {
241 Com_Printf("R_FindModel: Could not find: '%s'\n", name);
242 return nullptr;
243 }
244
245 /* register the new model only after the loading is finished */
246
247 /* find a free model slot spot */
248 for (i = 0, mod = r_models; i < r_numModels; i++, mod++) {
249 if (!mod->name[0])
250 break;
251 }
252 if (i == r_numModels) {
254 Com_Error(ERR_FATAL, "r_numModels == MAX_MOD_KNOWN");
255 r_numModels++;
256 }
257
258 /* copy the model to the slot */
259 r_models[i] = model;
260 return &r_models[i];
261}
262
269model_t* R_GetModel (const char* name)
270{
271 model_t* mod;
272 int i;
273
274 if (name[0] == '\0')
275 Com_Error(ERR_FATAL, "R_ModForName: nullptr name");
276
277 /* inline models are grabbed only from worldmodel */
278 if (name[0] == '*') {
279 i = atoi(name + 1) - 1;
281 Com_Error(ERR_FATAL, "bad inline model number '%s' (%i/%i)", name, i, r_numModelsInline);
282 return &r_modelsInline[i];
283 }
284
285 /* search the currently loaded models */
286 for (i = 0, mod = r_models; i < r_numModels; i++, mod++)
287 if (Q_streq(mod->name, name))
288 return mod;
289 return nullptr;
290}
291
292#define MEM_TAG_STATIC_MODELS 1
300{
303
304 /* mark the static model textures as it_static, thus R_FreeWorldImages
305 * won't free them */
306 int i;
307 model_t* mod;
308 for (i = 0, mod = r_models; i < r_numModelsStatic; i++, mod++) {
309 if (!mod->alias.num_meshes)
310 Com_Printf("Model '%s' has no meshes\n", mod->name);
311 for (int j = 0; j < mod->alias.num_meshes; j++) {
312 mAliasMesh_t* mesh = &mod->alias.meshes[j];
313 if (!mesh->num_skins)
314 Com_Printf("Model '%s' has no skins\n", mod->name);
315 for (int k = 0; k < mesh->num_skins; k++) {
316 mAliasSkin_t* modelSkin = &mesh->skins[k];
317 if (modelSkin->skin != r_noTexture)
318 modelSkin->skin->type = it_static;
319 else
320 Com_Printf("No skin for #%i of '%s'\n", j, mod->name);
321 }
322 }
323 }
324
325 Com_Printf("%i static models loaded\n", r_numModels);
326}
327
333{
335 return -1;
336
338
339 return r_numActorSkinName++;
340}
341
342bool R_UseActorSkin (void)
343{
344 return r_numActorSkinName != 0;
345}
346
347static const char* R_GetActorSkin (int id)
348{
349 assert(id >= 0 && id < r_numActorSkinName);
350 return r_actorSkinNames[id];
351}
352
358void R_LoadActorSkinsFromModel (mAliasMesh_t* outMesh, image_t* defaultSkin)
359{
360 assert(outMesh);
361
362 outMesh->num_skins = r_numActorSkinName;
364
365 if (defaultSkin == r_noTexture)
366 Com_Printf("R_LoadActorSkinsFromModel: No default skin found for model \"%s\"\n", outMesh->name);
367
368 for (int i = 0; i < outMesh->num_skins; i++) {
369 mAliasSkin_t* modelSkin = &outMesh->skins[i];
370 if (i == 0) {
371 modelSkin->skin = defaultSkin;
372 } else {
373 const char* skin = R_GetActorSkin(i);
374 modelSkin->skin = R_AliasModelGetSkin(nullptr, va("%s_%s", defaultSkin->name, skin));
376 if (modelSkin->skin == r_noTexture) {
377 Com_Printf("R_LoadActorSkinsFromModel: Skin %s_%s not found, defaulting to: %s\n",
378 defaultSkin->name, skin, defaultSkin->name);
379 modelSkin->skin = defaultSkin;
380 }
381 }
382 Q_strncpyz(modelSkin->name, modelSkin->skin->name, sizeof(outMesh->skins[i].name));
383 }
384}
385
391void R_ShutdownModels (bool complete)
392{
393 int i;
394 const int start = complete ? 0 : r_numModelsStatic;
395
396 /* free the vertex buffer - but not for the static models
397 * the world, the submodels and all the misc_models are located in the
398 * r_models array */
399 for (i = start; i < r_numModels; i++) {
400 model_t* mod = &r_models[i];
401 mBspModel_t* bsp = &mod->bsp;
402
403 if (bsp->vertex_buffer)
404 qglDeleteBuffers(1, &bsp->vertex_buffer);
405 if (bsp->texcoord_buffer)
406 qglDeleteBuffers(1, &bsp->texcoord_buffer);
407 if (bsp->lmtexcoord_buffer)
408 qglDeleteBuffers(1, &bsp->lmtexcoord_buffer);
409 if (bsp->normal_buffer)
410 qglDeleteBuffers(1, &bsp->normal_buffer);
411 if (bsp->tangent_buffer)
412 qglDeleteBuffers(1, &bsp->tangent_buffer);
413 if (bsp->index_buffer)
414 qglDeleteBuffers(1, &bsp->index_buffer);
415 }
416
417 /* don't free the static models with the tag MEM_TAG_STATIC_MODELS */
418 if (complete) {
419 if (vid_modelPool)
421 if (vid_lightPool)
423 r_numModels = 0;
425 r_numMapTiles = 0;
427 } else {
428 if (vid_modelPool)
430 if (vid_lightPool)
433 }
434}
435
437{
438}
439
441{
442 R_ShutdownModels(true);
443}
#define LittleLong(X)
Definition byte.h:37
memPool_t * vid_modelPool
Definition cl_main.cpp:90
memPool_t * vid_lightPool
Definition cl_main.cpp:89
void Com_Error(int code, const char *fmt,...)
Definition common.cpp:459
void Com_Printf(const char *const fmt,...)
Definition common.cpp:428
#define ERR_DROP
Definition common.h:211
#define ERR_FATAL
Definition common.h:210
#define MAX_MOD_KNOWN
Definition defines.h:160
int FS_CheckFile(const char *fmt,...)
Just returns the filelength and -1 if the file wasn't found.
Definition files.cpp:298
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition files.cpp:384
void FS_FreeFile(void *buffer)
Definition files.cpp:411
#define MAX_QPATH
Definition filesys.h:40
const char * filename
Definition ioapi.h:41
voidpf void * buf
Definition ioapi.h:42
#define Mem_FreePool(pool)
Definition mem.h:37
#define Mem_PoolAllocTypeN(type, n, pool)
Definition mem.h:42
#define Mem_ChangeTag(pool, tagFrom, tagTo)
Definition mem.h:52
#define Mem_FreeTag(pool, tagNum)
Definition mem.h:36
#define Mem_StrDup(in)
Definition mem.h:48
#define IDBSPHEADER
Definition qfiles.h:251
#define IDALIASHEADER
Definition qfiles.h:40
#define IDMD3HEADER
Definition qfiles.h:159
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition r_gl.h:110
QGL_EXTERN GLuint * id
Definition r_gl.h:86
image_t * r_noTexture
Definition r_main.cpp:51
@ it_static
Definition r_image.h:44
local graphics definitions
static char * r_actorSkinNames[MAX_ACTORSKINNAME]
Definition r_model.cpp:39
bool R_ModelExists(const char *name)
Definition r_model.cpp:177
static const char * R_GetActorSkin(int id)
Definition r_model.cpp:347
void R_LoadActorSkinsFromModel(mAliasMesh_t *outMesh, image_t *defaultSkin)
Load actor skins from a default skin to a a mesh.
Definition r_model.cpp:358
model_t * R_FindModel(const char *name)
Tries to load a model.
Definition r_model.cpp:203
void R_ModModellist_f(void)
Prints all loaded models.
Definition r_model.cpp:53
void R_ModelInit()
Definition r_model.cpp:436
void R_ModelShutdown()
Definition r_model.cpp:440
int R_ModAllocateActorSkin(const char *name)
Register an actorskin name.
Definition r_model.cpp:332
int r_numMapTiles
Definition r_model.cpp:33
void R_ShutdownModels(bool complete)
Frees the model pool.
Definition r_model.cpp:391
void R_SwitchModelMemPoolTag(void)
After all static models are loaded, switch the pool tag for these models to not free them everytime R...
Definition r_model.cpp:299
static int r_numModels
Definition r_model.cpp:29
static void R_LoadModelAsync(model_t *mod, byte *buf, int modfilelen)
Definition r_model.cpp:108
int r_numModelsInline
Definition r_model.cpp:37
static int r_numActorSkinName
Definition r_model.cpp:40
bool R_UseActorSkin(void)
Definition r_model.cpp:342
model_t * R_GetModel(const char *name)
Get a model for the given name already loaded.
Definition r_model.cpp:269
model_t r_modelsInline[MAX_MOD_KNOWN]
Definition r_model.cpp:36
static bool R_LoadModel(model_t *mod, const char *filename)
Loads in a model for the given name.
Definition r_model.cpp:157
model_t * r_mapTiles[MAX_MAPTILES]
The world model(s).
Definition r_model.cpp:32
static char const *const mod_extensions[]
all supported model formats
Definition r_model.cpp:46
#define MEM_TAG_STATIC_MODELS
Definition r_model.cpp:292
static model_t r_models[MAX_MOD_KNOWN]
Definition r_model.cpp:28
model_t * R_AllocModelSlot(void)
Definition r_model.cpp:100
static int r_numModelsStatic
Definition r_model.cpp:30
image_t * R_AliasModelGetSkin(const char *modelFileName, const char *skin)
#define MAX_ACTORSKINNAME
Definition r_model.h:66
@ mod_obj
Definition r_model.h:41
@ mod_bsp
Definition r_model.h:41
@ mod_alias_md3
Definition r_model.h:41
@ mod_bsp_submodel
Definition r_model.h:41
@ mod_alias_md2
Definition r_model.h:41
void R_ModLoadAnims(mAliasModel_t *mod, const char *animname)
void R_ModLoadAliasMD2Model(model_t *mod, byte *buffer, int bufSize, bool loadNormals)
Load MD2 models from file.
void R_ModLoadAliasMD3Model(model_t *mod, byte *buffer, int bufSize)
Load MD3 models from file.
void R_LoadObjModel(model_t *mod, byte *buffer, int bufSize)
#define Q_strcasecmp(a, b)
Definition shared.h:131
#define Q_streq(a, b)
Definition shared.h:136
#define OBJZERO(obj)
Definition shared.h:178
#define lengthof(x)
Definition shared.h:105
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
Definition shared.cpp:259
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition shared.cpp:457
void Com_DefaultExtension(char *path, size_t len, const char *extension)
Sets a default extension if there is none.
Definition shared.cpp:297
const char * Com_GetExtension(const char *path)
Definition shared.cpp:282
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition shared.cpp:494
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition shared.cpp:410
char name[MAX_QPATH]
Definition r_image.h:62
GLuint texnum
Definition r_image.h:66
imagetype_t type
Definition r_image.h:63
mAliasSkin_t * skins
char name[MODEL_MAX_PATH]
mAliasMesh_t * meshes
char name[MODEL_MAX_PATH]
image_t * skin
brush model
unsigned int tangent_buffer
unsigned int normal_buffer
unsigned int index_buffer
unsigned int vertex_buffer
unsigned int texcoord_buffer
unsigned int lmtexcoord_buffer
modtype_t type
Definition r_model.h:46
mBspModel_t bsp
Definition r_model.h:60
mAliasModel_t alias
Definition r_model.h:63
char name[MAX_QPATH]
Definition r_model.h:44
bool loaded
Definition r_model.h:54