UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
r_model.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 1997-2001 Id Software, Inc.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 
24 */
25 
26 #include "r_local.h"
27 
29 static int r_numModels;
30 static int r_numModelsStatic;
31 
32 model_t* r_mapTiles[MAX_MAPTILES];
34 
35 /* the inline * models from the current map are kept separate */
38 
40 static int r_numActorSkinName;
41 
46 static char const* const mod_extensions[] = {
47  "md2", "md3", "obj", nullptr
48 };
49 
53 void R_ModModellist_f (void)
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;
75  case mod_bsp_submodel:
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 */
103  if (r_numModels < 0 || r_numModels >= MAX_MOD_KNOWN)
104  Com_Error(ERR_DROP, "R_ModAddMapTile: r_numModels >= MAX_MOD_KNOWN");
105  return &r_models[r_numModels++];
106 }
107 
108 static 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 
146  FS_FreeFile(buf);
147 
148  mod->loaded = true;
149 }
150 
157 static 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 
177 bool 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 
203 model_t* R_FindModel (const char* name)
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) {
253  if (r_numModels == MAX_MOD_KNOWN)
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 
269 model_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;
280  if (i < 0 || i >= r_numModelsInline)
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
293 
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 
332 int R_ModAllocateActorSkin (const char* name)
333 {
335  return -1;
336 
338 
339  return r_numActorSkinName++;
340 }
341 
342 bool R_UseActorSkin (void)
343 {
344  return r_numActorSkinName != 0;
345 }
346 
347 static const char* R_GetActorSkin (int id)
348 {
349  assert(id >= 0 && id < r_numActorSkinName);
350  return r_actorSkinNames[id];
351 }
352 
358 void 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 
391 void 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;
424  r_numModelsInline = 0;
425  r_numMapTiles = 0;
426  OBJZERO(r_models);
427  } else {
428  if (vid_modelPool)
430  if (vid_lightPool)
432  r_numModels = r_numModelsStatic;
433  }
434 }
435 
436 void R_ModelInit ()
437 {
438 }
439 
441 {
442  R_ShutdownModels(true);
443 }
bool R_ModelExists(const char *name)
Definition: r_model.cpp:177
static bool R_LoadModel(model_t *mod, const char *filename)
Loads in a model for the given name.
Definition: r_model.cpp:157
#define IDALIASHEADER
Definition: qfiles.h:40
mAliasModel_t alias
Definition: r_model.h:63
int FS_CheckFile(const char *fmt,...)
Just returns the filelength and -1 if the file wasn't found.
Definition: files.cpp:298
memPool_t * vid_modelPool
Definition: cl_main.cpp:90
image_t * R_AliasModelGetSkin(const char *modelFileName, const char *skin)
unsigned int texcoord_buffer
void R_LoadObjModel(model_t *mod, byte *buffer, int bufSize)
const char * Com_GetExtension(const char *path)
Definition: shared.cpp:282
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
model_t * r_mapTiles[MAX_MAPTILES]
The world model(s)
Definition: r_model.cpp:32
bool loaded
Definition: r_model.h:54
mAliasSkin_t * skins
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
Definition: shared.cpp:259
const char * filename
Definition: ioapi.h:41
void R_ShutdownModels(bool complete)
Frees the model pool.
Definition: r_model.cpp:391
image_t * skin
Definition: r_model_alias.h:92
local graphics definitions
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition: files.cpp:384
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
static void R_LoadModelAsync(model_t *mod, byte *buf, int modfilelen)
Definition: r_model.cpp:108
image_t * r_noTexture
Definition: r_main.cpp:51
#define Mem_StrDup(in)
Definition: mem.h:48
model_t r_modelsInline[MAX_MOD_KNOWN]
Definition: r_model.cpp:36
voidpf void * buf
Definition: ioapi.h:42
#define ERR_FATAL
Definition: common.h:210
#define Mem_ChangeTag(pool, tagFrom, tagTo)
Definition: mem.h:52
int r_numMapTiles
Definition: r_model.cpp:33
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
char name[MODEL_MAX_PATH]
Definition: r_model_alias.h:90
static char const *const mod_extensions[]
all supported model formats
Definition: r_model.cpp:46
GLuint * id
Definition: r_gl.h:149
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
#define MEM_TAG_STATIC_MODELS
Definition: r_model.cpp:292
void R_ModelShutdown()
Definition: r_model.cpp:440
imagetype_t type
Definition: r_image.h:63
#define ERR_DROP
Definition: common.h:211
#define MAX_MOD_KNOWN
Definition: defines.h:160
#define IDMD3HEADER
Definition: qfiles.h:159
char name[MODEL_MAX_PATH]
#define OBJZERO(obj)
Definition: shared.h:178
modtype_t type
Definition: r_model.h:46
char name[MAX_QPATH]
Definition: r_image.h:62
unsigned int normal_buffer
model_t * R_AllocModelSlot(void)
Definition: r_model.cpp:100
void R_ModModellist_f(void)
Prints all loaded models.
Definition: r_model.cpp:53
unsigned int tangent_buffer
#define MAX_ACTORSKINNAME
Definition: r_model.h:66
char name[MAX_QPATH]
Definition: r_model.h:44
void R_ModLoadAliasMD2Model(model_t *mod, byte *buffer, int bufSize, bool loadNormals)
Load MD2 models from file.
model_t * R_FindModel(const char *name)
Tries to load a model.
Definition: r_model.cpp:203
memPool_t * vid_lightPool
Definition: cl_main.cpp:89
#define Q_strcasecmp(a, b)
Definition: shared.h:131
int r_numModelsInline
Definition: r_model.cpp:37
#define Mem_FreePool(pool)
Definition: mem.h:37
unsigned int vertex_buffer
void R_ModLoadAliasMD3Model(model_t *mod, byte *buffer, int bufSize)
Load MD3 models from file.
Definition: r_model_md3.cpp:38
int R_ModAllocateActorSkin(const char *name)
Register an actorskin name.
Definition: r_model.cpp:332
#define Mem_PoolAllocTypeN(type, n, pool)
Definition: mem.h:42
mAliasMesh_t * meshes
unsigned int lmtexcoord_buffer
void R_ModelInit()
Definition: r_model.cpp:436
void R_ModLoadAnims(mAliasModel_t *mod, const char *animname)
static int r_numModelsStatic
Definition: r_model.cpp:30
void Com_DefaultExtension(char *path, size_t len, const char *extension)
Sets a default extension if there is none.
Definition: shared.cpp:297
#define Mem_FreeTag(pool, tagNum)
Definition: mem.h:36
#define MAX_QPATH
Definition: filesys.h:40
QGL_EXTERN GLint i
Definition: r_gl.h:113
static int r_numModels
Definition: r_model.cpp:29
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
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
static int r_numActorSkinName
Definition: r_model.cpp:40
#define IDBSPHEADER
Definition: qfiles.h:251
brush model
model_t * R_GetModel(const char *name)
Get a model for the given name already loaded.
Definition: r_model.cpp:269
#define lengthof(x)
Definition: shared.h:105
static char * r_actorSkinNames[MAX_ACTORSKINNAME]
Definition: r_model.cpp:39
static model_t r_models[MAX_MOD_KNOWN]
Definition: r_model.cpp:28
#define Q_streq(a, b)
Definition: shared.h:136
static const char * R_GetActorSkin(int id)
Definition: r_model.cpp:347
uint8_t byte
Definition: ufotypes.h:34
unsigned int index_buffer
void FS_FreeFile(void *buffer)
Definition: files.cpp:411
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
#define LittleLong(X)
Definition: byte.h:37
GLuint texnum
Definition: r_image.h:66
mBspModel_t bsp
Definition: r_model.h:60
bool R_UseActorSkin(void)
Definition: r_model.cpp:342