UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
r_model_md2.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 
28 /*
29 ==============================================================================
30 MD2 ALIAS MODELS
31 ==============================================================================
32 */
33 
34 static void R_ModLoadTags (model_t* mod, void* buffer, int bufSize)
35 {
36  dMD2tag_t* pintag = (dMD2tag_t*) buffer;
37 
38  int version = LittleLong(pintag->version);
39  if (version != TAG_VERSION)
40  Com_Error(ERR_FATAL, "R_ModLoadTags: tag has wrong version number (%i should be %i)", version, TAG_VERSION);
41 
42  /* byte swap the header fields and sanity check */
43  dMD2tag_t pheader;
44  pheader.ident = LittleLong(pintag->ident);
45  pheader.version = LittleLong(pintag->version);
46  pheader.num_tags = LittleLong(pintag->num_tags);
47  pheader.num_frames = LittleLong(pintag->num_frames);
48  pheader.ofs_names = LittleLong(pintag->ofs_names);
49  pheader.ofs_tags = LittleLong(pintag->ofs_tags);
50  pheader.ofs_end = LittleLong(pintag->ofs_end);
51  pheader.ofs_extractend = LittleLong(pintag->ofs_extractend);
52 
53  if (pheader.num_tags <= 0)
54  Com_Error(ERR_FATAL, "R_ModLoadTags: tag file for %s has no tags", mod->name);
55 
56  if (pheader.num_frames <= 0)
57  Com_Error(ERR_FATAL, "R_ModLoadTags: tag file for %s has no frames", mod->name);
58 
59  /* load tag matrices */
60  float* inmat = (float*) ((byte*) pintag + pheader.ofs_tags);
61 
62  if (bufSize != pheader.ofs_end)
63  Com_Error(ERR_FATAL, "R_ModLoadTags: tagfile %s is broken - expected: %i, offsets tell us to read: %i",
64  mod->name, bufSize, pheader.ofs_end);
65 
66  if (pheader.num_frames != mod->alias.num_frames)
67  Com_Printf("R_ModLoadTags: found %i frames in %s but model has %i frames\n",
68  pheader.num_frames, mod->name, mod->alias.num_frames);
69 
70  if (pheader.ofs_names != 32)
71  Com_Error(ERR_FATAL, "R_ModLoadTags: invalid ofs_name in tagfile for %s", mod->name);
72  if (pheader.ofs_tags != pheader.ofs_names + (pheader.num_tags * 64))
73  Com_Error(ERR_FATAL, "R_ModLoadTags: invalid ofs_tags for tagfile %s", mod->name);
74  /* (4 * 3) * 4 bytes (int) */
75  if (pheader.ofs_end != pheader.ofs_tags + (pheader.num_tags * pheader.num_frames * 48))
76  Com_Error(ERR_FATAL, "R_ModLoadTags: invalid ofs_end for tagfile %s", mod->name);
77  /* (4 * 4) * 4 bytes (int) */
78  if (pheader.ofs_extractend != pheader.ofs_tags + (pheader.num_tags * pheader.num_frames * 64))
79  Com_Error(ERR_FATAL, "R_ModLoadTags: invalid ofs_extractend for tagfile %s", mod->name);
80 
81  mod->alias.num_tags = pheader.num_tags;
83 
84  for (int j = 0; j < pheader.num_tags; j++, pouttag++) {
86  memcpy(pouttag->name, (char*) pintag + pheader.ofs_names + j * MD2_MAX_SKINNAME, sizeof(pouttag->name));
87  for (int i = 0; i < pheader.num_frames; i++, pouttagorient++) {
88  for (int k = 0; k < 3; k++) {
89  pouttagorient->axis[k][0] = LittleFloat(*inmat++);
90  pouttagorient->axis[k][1] = LittleFloat(*inmat++);
91  pouttagorient->axis[k][2] = LittleFloat(*inmat++);
92  }
93  VectorSet(pouttagorient->origin, LittleFloat(*inmat++), LittleFloat(*inmat++), LittleFloat(*inmat++));
94  }
95  }
96 }
97 
101 static void R_ModLoadAliasMD2MeshUnindexed (model_t* mod, const dMD2Model_t* md2, int bufSize, bool loadNormals)
102 {
103  int i, j;
104  const dMD2Triangle_t* pintri;
105  const dMD2Coord_t* pincoord;
106  mAliasMesh_t* outMesh;
107  mAliasFrame_t* outFrameTmp;
108  int32_t tempIndex[MD2_MAX_TRIANGLES * 3];
109  int32_t tempSTIndex[MD2_MAX_TRIANGLES * 3];
110  int indRemap[MD2_MAX_TRIANGLES * 3];
111  int frameSize, numVerts;
112  double isw;
113  int md2Verts;
114 
115  outMesh = &mod->alias.meshes[mod->alias.num_meshes - 1];
116 
117  Q_strncpyz(outMesh->name, mod->name, sizeof(outMesh->name));
118  md2Verts = LittleLong(md2->num_verts);
119  if (md2Verts <= 0 || md2Verts >= MD2_MAX_VERTS)
120  Com_Error(ERR_DROP, "model %s has too many (or no) vertices (%i/%i)",
121  mod->name, md2Verts, MD2_MAX_VERTS);
122  outMesh->num_tris = LittleLong(md2->num_tris);
123  if (outMesh->num_tris <= 0 || outMesh->num_tris >= MD2_MAX_TRIANGLES)
124  Com_Error(ERR_DROP, "model %s has too many (or no) triangles (%i/%i)",
125  mod->name, outMesh->num_tris, MD2_MAX_TRIANGLES);
126  frameSize = LittleLong(md2->framesize);
127  outMesh->num_verts = md2Verts;
128 
129  if (mod->alias.num_meshes == 1) {
130  const char* md2Path;
131  if (R_UseActorSkin() && LittleLong(md2->num_skins) == 1 && Q_strstart(outMesh->name, "models/soldiers/")) {
132  image_t* defaultSkin;
133  md2Path = (const char*) md2 + LittleLong(md2->ofs_skins);
134  defaultSkin = R_AliasModelGetSkin(mod->name, md2Path);
135  R_LoadActorSkinsFromModel(outMesh, defaultSkin);
136 
138  outMesh->skinWidth = LittleLong(md2->skinwidth);
139  outMesh->skinHeight = LittleLong(md2->skinheight);
140  } else {
141  /* load the skins */
142  outMesh->num_skins = LittleLong(md2->num_skins);
143  if (outMesh->num_skins <= 0 || outMesh->num_skins >= MD2_MAX_SKINS)
144  Com_Error(ERR_DROP, "Could not load model '%s' - invalid num_skins value: %i", mod->name, outMesh->num_skins);
145 
147  md2Path = (const char*) md2 + LittleLong(md2->ofs_skins);
148  for (i = 0; i < outMesh->num_skins; i++) {
149  outMesh->skins[i].skin = R_AliasModelGetSkin(mod->name, md2Path + i * MD2_MAX_SKINNAME);
150  Q_strncpyz(outMesh->skins[i].name, outMesh->skins[i].skin->name, sizeof(outMesh->skins[i].name));
151  }
152 
153  outMesh->skinWidth = LittleLong(md2->skinwidth);
154  outMesh->skinHeight = LittleLong(md2->skinheight);
155  }
156 
157  if (outMesh->skinHeight <= 0 || outMesh->skinWidth <= 0)
158  Com_Error(ERR_DROP, "model %s has invalid skin dimensions '%d x %d'",
159  mod->name, outMesh->skinHeight, outMesh->skinWidth);
160  } else {
161  /* skin data must be the same for the lod meshes */
162  outMesh->num_skins = mod->alias.meshes[0].num_skins;
163  outMesh->skins = mod->alias.meshes[0].skins;
164  outMesh->skinWidth = mod->alias.meshes[0].skinWidth;
165  outMesh->skinHeight = mod->alias.meshes[0].skinHeight;
166  }
167 
168  isw = 1.0 / (double)outMesh->skinWidth;
169 
170  /* load triangle lists */
171  pintri = (const dMD2Triangle_t*) ((const byte*) md2 + LittleLong(md2->ofs_tris));
172  pincoord = (const dMD2Coord_t*) ((const byte*) md2 + LittleLong(md2->ofs_st));
173 
174  for (i = 0; i < outMesh->num_tris; i++) {
175  for (j = 0; j < 3; j++) {
176  tempIndex[i * 3 + j] = (int32_t)LittleShort(pintri[i].index_verts[j]);
177  tempSTIndex[i * 3 + j] = (int32_t)LittleShort(pintri[i].index_st[j]);
178  }
179  }
180 
181  /* build list of unique vertices */
182  outMesh->num_indexes = outMesh->num_tris * 3;
183  numVerts = 0;
184  int32_t* const outIndex = outMesh->indexes = Mem_PoolAllocTypeN(int32_t, outMesh->num_indexes, vid_modelPool);
185 
186  for (i = 0; i < outMesh->num_indexes; i++)
187  indRemap[i] = -1;
188 
189  for (i = 0; i < outMesh->num_indexes; i++) {
190  if (indRemap[i] != -1)
191  continue;
192 
193  /* remap duplicates */
194  for (j = i + 1; j < outMesh->num_indexes; j++) {
195  if (tempIndex[j] != tempIndex[i])
196  continue;
197  if (pincoord[tempSTIndex[j]].s != pincoord[tempSTIndex[i]].s
198  || pincoord[tempSTIndex[j]].t != pincoord[tempSTIndex[i]].t)
199  continue;
200 
201  indRemap[j] = i;
202  outIndex[j] = numVerts;
203  }
204 
205  /* add unique vertex */
206  indRemap[i] = i;
207  outIndex[i] = numVerts++;
208  }
209 
210  if (numVerts >= 4096)
211  Com_Printf("model %s has more than 4096 verts (original verts: %i and tris: %i)\n",
212  mod->name, outMesh->num_verts, outMesh->num_tris);
213 
214  outMesh->num_verts = numVerts;
215  if (outMesh->num_verts <= 0 || outMesh->num_verts >= MAX_ALIAS_VERTS)
216  Com_Error(ERR_DROP, "R_ModLoadAliasMD2Mesh: invalid amount of verts for model '%s' (verts: %i, tris: %i)\n",
217  mod->name, outMesh->num_verts, outMesh->num_tris);
218 
219  for (i = 0; i < outMesh->num_indexes; i++) {
220  if (indRemap[i] == i)
221  continue;
222 
223  outIndex[i] = outIndex[indRemap[i]];
224  }
225 
226  mAliasCoord_t* const outCoord = outMesh->stcoords = Mem_PoolAllocTypeN(mAliasCoord_t, outMesh->num_verts, vid_modelPool);
227  for (j = 0; j < outMesh->num_indexes; j++) {
228  outCoord[outIndex[j]][0] = (float)(((double)LittleShort(pincoord[tempSTIndex[indRemap[j]]].s) + 0.5) * isw);
229  outCoord[outIndex[j]][1] = (float)(((double)LittleShort(pincoord[tempSTIndex[indRemap[j]]].t) + 0.5) * isw);
230  }
231 
232  /* load the frames */
235  if (mod->alias.num_meshes == 1)
236  mod->alias.frames = outFrame;
237  else if (mod->alias.num_frames != LittleLong(md2->num_frames))
238  Com_Error(ERR_DROP, "R_ModLoadAliasMD2Mesh: invalid amount of frames for lod model for '%s'\n", mod->name);
239 
240  for (i = 0; i < mod->alias.num_frames; i++, outFrame++, outVertex += numVerts) {
241  const dMD2Frame_t* pinframe = (const dMD2Frame_t*) ((const byte*) md2 + LittleLong(md2->ofs_frames) + i * frameSize);
242 
243  for (j = 0; j < 3; j++)
244  outFrame->scale[j] = LittleFloat(pinframe->scale[j]);
245 
246  if (mod->alias.num_meshes == 1) {
247  for (j = 0; j < 3; j++)
248  outFrame->translate[j] = LittleFloat(pinframe->translate[j]);
249 
250  VectorCopy(outFrame->translate, outFrame->fBox.mins);
251  VectorMA(outFrame->translate, 255, outFrame->scale, outFrame->fBox.maxs);
252 
253  mod->modBox.add(outFrame->fBox);
254  }
255 
256  for (j = 0; j < outMesh->num_indexes; j++) {
257  const int index = tempIndex[indRemap[j]];
258  const dMD2TriangleVertex_t* v = &pinframe->verts[index];
259  float* ov = outVertex[outIndex[j]].point;
260  ov[0] = (int16_t)v->v[0] * outFrame->scale[0];
261  ov[1] = (int16_t)v->v[1] * outFrame->scale[1];
262  ov[2] = (int16_t)v->v[2] * outFrame->scale[2];
263  }
264  }
265 
266  /* Calculate normals and tangents */
267  if (loadNormals)
269 
270  if (mod->alias.num_meshes > 1)
271  Mem_Free(outFrameTmp);
272 }
273 
277 static void R_ModLoadAliasMD2MeshIndexed (model_t* mod, const dMD2Model_t* md2, int bufSize)
278 {
279  int i, j;
280  const dMD2Triangle_t* pintri;
281  const dMD2Coord_t* pincoord;
282  mAliasMesh_t* outMesh;
283  mAliasFrame_t* outFrameTmp;
284  mAliasVertex_t* outVertex;
285  int32_t tempIndex[MD2_MAX_TRIANGLES * 3];
286  int32_t tempSTIndex[MD2_MAX_TRIANGLES * 3];
287  int32_t* outIndex;
288  int frameSize, numIndexes, numVerts;
289  double isw;
290  int md2Verts;
291 
292  outMesh = &mod->alias.meshes[mod->alias.num_meshes - 1];
293 
294  Q_strncpyz(outMesh->name, mod->name, sizeof(outMesh->name));
295  md2Verts = LittleLong(md2->num_verts);
296  if (md2Verts <= 0 || md2Verts >= MD2_MAX_VERTS)
297  Com_Error(ERR_DROP, "model %s has too many (or no) vertices (%i/%i)",
298  mod->name, md2Verts, MD2_MAX_VERTS);
299  outMesh->num_tris = LittleLong(md2->num_tris);
300  if (outMesh->num_tris <= 0 || outMesh->num_tris >= MD2_MAX_TRIANGLES)
301  Com_Error(ERR_DROP, "model %s has too many (or no) triangles (%i/%i)",
302  mod->name, outMesh->num_tris, MD2_MAX_TRIANGLES);
303  frameSize = LittleLong(md2->framesize);
304 
305  if (outMesh->num_verts >= 4096)
306  Com_Printf("model %s has more than 4096 verts\n", mod->name);
307 
308  if (outMesh->num_verts <= 0 || outMesh->num_verts >= MAX_ALIAS_VERTS)
309  Com_Error(ERR_DROP, "R_ModLoadAliasMD2Mesh: invalid amount of verts for model '%s' (verts: %i, tris: %i)",
310  mod->name, outMesh->num_verts, outMesh->num_tris);
311 
312  if (mod->alias.num_meshes == 1) {
313  /* load the skins */
314  outMesh->num_skins = LittleLong(md2->num_skins);
315  if (outMesh->num_skins <= 0 || outMesh->num_skins >= MD2_MAX_SKINS)
316  Com_Error(ERR_DROP, "Could not load model '%s' - invalid num_skins value: %i\n", mod->name, outMesh->num_skins);
317 
319  const char* md2Path = (const char*) md2 + LittleLong(md2->ofs_skins);
320  for (i = 0; i < outMesh->num_skins; i++) {
321  outMesh->skins[i].skin = R_AliasModelGetSkin(mod->name, md2Path + i * MD2_MAX_SKINNAME);
322  Q_strncpyz(outMesh->skins[i].name, outMesh->skins[i].skin->name, sizeof(outMesh->skins[i].name));
323  }
324 
325  outMesh->skinWidth = LittleLong(md2->skinwidth);
326  outMesh->skinHeight = LittleLong(md2->skinheight);
327 
328  if (outMesh->skinHeight <= 0 || outMesh->skinWidth <= 0)
329  Com_Error(ERR_DROP, "model %s has invalid skin dimensions '%d x %d'",
330  mod->name, outMesh->skinHeight, outMesh->skinWidth);
331  } else {
332  /* skin data must be the same for the lod meshes */
333  outMesh->num_skins = mod->alias.meshes[0].num_skins;
334  outMesh->skins = mod->alias.meshes[0].skins;
335  outMesh->skinWidth = mod->alias.meshes[0].skinWidth;
336  outMesh->skinHeight = mod->alias.meshes[0].skinHeight;
337  }
338 
339  isw = 1.0 / (double)outMesh->skinWidth;
340 
341  /* load triangle lists */
342  pintri = (const dMD2Triangle_t*) ((const byte*) md2 + LittleLong(md2->ofs_tris));
343  pincoord = (const dMD2Coord_t*) ((const byte*) md2 + LittleLong(md2->ofs_st));
344 
345  for (i = 0; i < outMesh->num_tris; i++) {
346  for (j = 0; j < 3; j++) {
347  tempIndex[i * 3 + j] = (int32_t)LittleShort(pintri[i].index_verts[j]);
348  tempSTIndex[i * 3 + j] = (int32_t)LittleShort(pintri[i].index_st[j]);
349  }
350  }
351 
352  /* build list of unique vertices */
353  numIndexes = outMesh->num_tris * 3;
354  numVerts = outMesh->num_verts;
355 
356  if (numIndexes != outMesh->num_indexes)
357  Com_Error(ERR_DROP, "mdx and model file differ: %s", mod->name);
358 
359  mAliasCoord_t* const outCoord = outMesh->stcoords = Mem_PoolAllocTypeN(mAliasCoord_t, outMesh->num_verts, vid_modelPool);
360  outIndex = outMesh->indexes;
361  for (j = 0; j < outMesh->num_indexes; j++) {
362  const int32_t index = outIndex[j];
363  outCoord[index][0] = (float)(((double)LittleShort(pincoord[tempSTIndex[j]].s) + 0.5) * isw);
364  outCoord[index][1] = (float)(((double)LittleShort(pincoord[tempSTIndex[j]].t) + 0.5) * isw);
365  }
366 
367  /* load the frames */
369  outVertex = outMesh->vertexes;
370  if (mod->alias.num_meshes == 1)
371  mod->alias.frames = outFrame;
372  else if (mod->alias.num_frames != LittleLong(md2->num_frames))
373  Com_Error(ERR_DROP, "R_ModLoadAliasMD2Mesh: invalid amount of frames for lod model for '%s'\n", mod->name);
374 
375  for (i = 0; i < mod->alias.num_frames; i++, outFrame++, outVertex += numVerts) {
376  const dMD2Frame_t* pinframe = (const dMD2Frame_t*) ((const byte*) md2 + LittleLong(md2->ofs_frames) + i * frameSize);
377 
378  for (j = 0; j < 3; j++)
379  outFrame->scale[j] = LittleFloat(pinframe->scale[j]);
380 
381  if (mod->alias.num_meshes == 1) {
382  for (j = 0; j < 3; j++)
383  outFrame->translate[j] = LittleFloat(pinframe->translate[j]);
384 
385  VectorCopy(outFrame->translate, outFrame->fBox.mins);
386  VectorMA(outFrame->translate, 255, outFrame->scale, outFrame->fBox.maxs);
387 
388  mod->modBox.add(outFrame->fBox);
389  }
390 
391  for (j = 0; j < outMesh->num_indexes; j++) {
392  const int index = tempIndex[j];
393  const dMD2TriangleVertex_t* v = &pinframe->verts[index];
394  float* ov = outVertex[outIndex[j]].point;
395  ov[0] = (int16_t)v->v[0] * outFrame->scale[0];
396  ov[1] = (int16_t)v->v[1] * outFrame->scale[1];
397  ov[2] = (int16_t)v->v[2] * outFrame->scale[2];
398  }
399  }
400 
401  if (mod->alias.num_meshes > 1)
402  Mem_Free(outFrameTmp);
403 }
404 
408 static void R_ModLoadAliasMD2Mesh (model_t* mod, const dMD2Model_t* md2, int bufSize, bool loadNormals)
409 {
410  int version;
411  size_t size;
412 
413  /* sanity checks */
414  version = LittleLong(md2->version);
415  if (version != MD2_ALIAS_VERSION)
416  Com_Error(ERR_DROP, "%s has wrong version number (%i should be %i)", mod->name, version, MD2_ALIAS_VERSION);
417 
418  if (bufSize != LittleLong(md2->ofs_end))
419  Com_Error(ERR_DROP, "model %s broken offset values (%i, %i)", mod->name, bufSize, LittleLong(md2->ofs_end));
420 
421  mod->alias.num_meshes++;
422  size = sizeof(mAliasMesh_t) * mod->alias.num_meshes;
423 
424  if (mod->alias.meshes == nullptr)
426  else {
427  mod->alias.meshes = (mAliasMesh_t*)Mem_ReAlloc(mod->alias.meshes, size);
428  }
429 
430  if (loadNormals) {
431  /* try to load normals and tangents */
432  if (R_ModLoadMDX(mod)) {
433  R_ModLoadAliasMD2MeshIndexed(mod, md2, bufSize);
434  } else {
435  /* compute normals and tangents */
436  R_ModLoadAliasMD2MeshUnindexed(mod, md2, bufSize, true);
437  }
438  } else {
439  /* don't load normals and tangents */
440  R_ModLoadAliasMD2MeshUnindexed(mod, md2, bufSize, false);
441  }
442 }
443 
450 static void R_ModLoadLevelOfDetailData (model_t* mod, bool loadNormals)
451 {
452  char base[MAX_QPATH];
453  int i;
454 
455  Com_StripExtension(mod->name, base, sizeof(base));
456 
457  for (i = 1; i <= 3; i++) {
458  if (FS_CheckFile("%s-lod%02i.md2", base, i) != -1) {
459  byte* buf;
460  int bufSize;
461  char fileName[MAX_QPATH];
462  const dMD2Model_t* md2;
463 
464  Com_Printf("found lod model for %s\n", mod->name);
465 
466  Com_sprintf(fileName, sizeof(fileName), "%s-lod%02i.md2", base, i);
467  /* load the file */
468  bufSize = FS_LoadFile(fileName, &buf);
469  if (!buf)
470  return;
471 
472  /* get the disk data */
473  md2 = (const dMD2Model_t*) buf;
474 
475  R_ModLoadAliasMD2Mesh(mod, md2, bufSize, loadNormals);
476 
477  FS_FreeFile(buf);
478  }
479  }
480 }
481 
485 void R_ModLoadAliasMD2Model (model_t* mod, byte* buffer, int bufSize, bool loadNormals)
486 {
487  dMD2Model_t* md2;
488  byte* tagbuf = nullptr;
489  char tagname[MAX_QPATH];
490 
491  /* get the disk data */
492  md2 = (dMD2Model_t*) buffer;
493 
494  /* only one mesh for md2 models */
495  mod->alias.num_frames = LittleLong(md2->num_frames);
496  if (mod->alias.num_frames <= 0 || mod->alias.num_frames >= MD2_MAX_FRAMES)
497  Com_Error(ERR_DROP, "model %s has too many (or no) frames", mod->name);
498 
499  /* fixed values */
500  mod->type = mod_alias_md2;
501 
502  mod->modBox.setNegativeVolume();
503 
504  R_ModLoadAliasMD2Mesh(mod, md2, bufSize, loadNormals);
505 
506  /* load the tags */
507  Com_StripExtension(mod->name, tagname, sizeof(tagname));
508  Com_DefaultExtension(tagname, sizeof(tagname), ".tag");
509 
510  /* try to load the tag file */
511  if (FS_CheckFile("%s", tagname) != -1) {
512  /* load the tags */
513  const int size = FS_LoadFile(tagname, &tagbuf);
514  R_ModLoadTags(mod, tagbuf, size);
515  FS_FreeFile(tagbuf);
516  }
517 
518  R_ModLoadLevelOfDetailData(mod, loadNormals);
519 
520  R_ModLoadArrayData(&mod->alias, mod->alias.meshes, loadNormals);
521 }
mAliasTag_t * tags
uint32_t skinheight
Definition: qfiles.h:118
#define VectorCopy(src, dest)
Definition: vector.h:51
uint32_t num_skins
Definition: qfiles.h:121
void setNegativeVolume()
Sets mins and maxs to their starting points before using addPoint.
Definition: aabb.h:98
#define Mem_ReAlloc(ptr, size)
Definition: mem.h:44
#define MD2_MAX_SKINS
Definition: qfiles.h:48
mAliasModel_t alias
Definition: r_model.h:63
bool R_ModLoadMDX(model_t *mod)
Tries to load a mdx file that contains the normals and the tangents for a model.
uint32_t num_tris
Definition: qfiles.h:124
#define VectorSet(v, x, y, z)
Definition: vector.h:59
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
void VectorMA(const vec3_t veca, const float scale, const vec3_t vecb, vec3_t outVector)
Sets vector_out (vc) to vevtor1 (va) + scale * vector2 (vb)
Definition: mathlib.cpp:261
image_t * R_AliasModelGetSkin(const char *modelFileName, const char *skin)
AABB modBox
Definition: r_model.h:51
#define MD2_ALIAS_VERSION
Definition: qfiles.h:42
mAliasVertex_t * vertexes
is a variable sized structure, however all frame_t structures within the same file will have the same...
Definition: qfiles.h:90
int32_t * indexes
uint32_t ofs_extractend
Definition: qfiles.h:152
uint32_t num_frames
Definition: qfiles.h:146
mAliasSkin_t * skins
mAliasTagOrientation_t * orient
Definition: r_model_alias.h:86
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
These two shorts are used to map a vertex onto a skin The horizontal axis position is given by s...
Definition: qfiles.h:57
struct mAliasMesh_s mAliasMesh_t
#define Mem_PoolAlloc(size, pool, tagNum)
Definition: mem.h:41
image_t * skin
Definition: r_model_alias.h:92
static void R_ModLoadAliasMD2MeshIndexed(model_t *mod, const dMD2Model_t *md2, int bufSize)
Assume that the indexArray is already filled, and load data for the model accordingly.
Tag file header structure - 32 byte A tag for a model must have the same amount of frames as the mode...
Definition: qfiles.h:141
local graphics definitions
int FS_LoadFile(const char *path, byte **buffer)
Filenames are relative to the quake search path.
Definition: files.cpp:384
#define MD2_MAX_SKINNAME
Definition: qfiles.h:49
void Com_Printf(const char *const fmt,...)
Definition: common.cpp:386
float translate[3]
Definition: qfiles.h:92
uint32_t ofs_end
Definition: qfiles.h:151
#define mAliasCoord_t
Definition: r_model_alias.h:32
int32_t num_indexes
static void R_ModLoadAliasMD2Mesh(model_t *mod, const dMD2Model_t *md2, int bufSize, bool loadNormals)
See if the model has an MDX file, and then load the model data appropriately for either case...
uint32_t ofs_end
Definition: qfiles.h:133
voidpf void * buf
Definition: ioapi.h:42
#define ERR_FATAL
Definition: common.h:210
uint32_t ident
Definition: qfiles.h:142
uint32_t version
Definition: qfiles.h:143
void Com_Error(int code, const char *fmt,...)
Definition: common.cpp:417
char name[MODEL_MAX_PATH]
Definition: r_model_alias.h:90
uint32_t framesize
Definition: qfiles.h:119
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
#define LittleShort(X)
Definition: byte.h:35
void add(const vec3_t point)
If the point is outside the box, expand the box to accommodate it.
Definition: aabb.cpp:57
#define ERR_DROP
Definition: common.h:211
GLsizei size
Definition: r_gl.h:152
char name[MODEL_MAX_PATH]
char name[MODEL_MAX_PATH]
Definition: r_model_alias.h:84
modtype_t type
Definition: r_model.h:46
char name[MAX_QPATH]
Definition: r_image.h:62
#define TAG_VERSION
Definition: qfiles.h:43
void R_ModCalcUniqueNormalsAndTangents(mAliasMesh_t *mesh, int nFrames, float smoothness)
Calculates normals and tangents for all frames and does vertex merging based on smoothness.
uint32_t ofs_tags
Definition: qfiles.h:150
uint32_t ofs_skins
Definition: qfiles.h:128
#define MD2_MAX_VERTS
Definition: qfiles.h:46
float scale[3]
Definition: qfiles.h:91
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition: shared.cpp:587
char name[MAX_QPATH]
Definition: r_model.h:44
uint32_t ofs_names
Definition: qfiles.h:149
void R_ModLoadAliasMD2Model(model_t *mod, byte *buffer, int bufSize, bool loadNormals)
Load MD2 models from file.
uint32_t num_tags
Definition: qfiles.h:145
uint32_t num_frames
Definition: qfiles.h:126
uint32_t ofs_frames
Definition: qfiles.h:131
static void R_ModLoadAliasMD2MeshUnindexed(model_t *mod, const dMD2Model_t *md2, int bufSize, bool loadNormals)
Assume that the indexArray is NOT filled, and load data for the model accordingly.
QGL_EXTERN GLuint index
Definition: r_gl.h:110
uint32_t ofs_tris
Definition: qfiles.h:130
mAliasMesh_t * meshes
#define Mem_PoolAllocTypeN(type, n, pool)
Definition: mem.h:42
void Com_DefaultExtension(char *path, size_t len, const char *extension)
Sets a default extension if there is none.
Definition: shared.cpp:297
the glcmd format: a positive integer starts a tristrip command, followed by that many vertex structur...
Definition: qfiles.h:109
uint32_t ofs_st
Definition: qfiles.h:129
#define MAX_QPATH
Definition: filesys.h:40
QGL_EXTERN GLint i
Definition: r_gl.h:113
static void R_ModLoadTags(model_t *mod, void *buffer, int bufSize)
Definition: r_model_md2.cpp:34
#define MD2_MAX_TRIANGLES
Definition: qfiles.h:45
#define Mem_Free(ptr)
Definition: mem.h:35
uint32_t version
Definition: qfiles.h:115
mAliasCoord_t * stcoords
int32_t num_verts
#define MAX_ALIAS_VERTS
Definition: r_model_alias.h:30
uint32_t num_verts
Definition: qfiles.h:122
uint8_t byte
Definition: ufotypes.h:34
QGL_EXTERN int GLboolean GLfloat * v
Definition: r_gl.h:120
static void R_ModLoadLevelOfDetailData(model_t *mod, bool loadNormals)
Adds new meshes to md2 models for different level of detail meshes.
QGL_EXTERN GLuint GLsizei bufSize
Definition: r_gl.h:110
uint32_t skinwidth
Definition: qfiles.h:117
mAliasFrame_t * frames
#define MD2_MAX_FRAMES
Definition: qfiles.h:47
void R_ModLoadArrayData(mAliasModel_t *mod, mAliasMesh_t *mesh, bool loadNormals)
Allocates data arrays for animated models. Only called once at loading time.
#define LittleFloat(X)
Definition: byte.h:57
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
dMD2TriangleVertex_t verts[1]
Definition: qfiles.h:94
bool R_UseActorSkin(void)
Definition: r_model.cpp:342