UFO: Alien Invasion
Loading...
Searching...
No Matches
r_model_md2.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
28/*
29==============================================================================
30MD2 ALIAS MODELS
31==============================================================================
32*/
33
34static 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
101static 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
277static 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
408static 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 {
428 }
429
430 if (loadNormals) {
431 /* try to load normals and tangents */
432 if (R_ModLoadMDX(mod)) {
434 } else {
435 /* compute normals and tangents */
437 }
438 } else {
439 /* don't load normals and tangents */
440 R_ModLoadAliasMD2MeshUnindexed(mod, md2, bufSize, false);
441 }
442}
443
450static 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
478 }
479 }
480}
481
485void 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 */
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
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}
#define LittleLong(X)
Definition byte.h:37
#define LittleShort(X)
Definition byte.h:35
#define LittleFloat(X)
Definition byte.h:57
memPool_t * vid_modelPool
Definition cl_main.cpp:90
vec3_t maxs
Definition aabb.h:258
void setNegativeVolume()
Sets mins and maxs to their starting points before using addPoint.
Definition aabb.h:98
vec3_t mins
Definition aabb.h:257
void add(const vec3_t point)
If the point is outside the box, expand the box to accommodate it.
Definition aabb.cpp:57
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
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
voidpf void uLong size
Definition ioapi.h:42
voidpf void * buf
Definition ioapi.h:42
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
#define Mem_PoolAllocTypeN(type, n, pool)
Definition mem.h:42
#define Mem_Free(ptr)
Definition mem.h:35
#define Mem_ReAlloc(ptr, size)
Definition mem.h:44
#define Mem_PoolAlloc(size, pool, tagNum)
Definition mem.h:41
#define MD2_MAX_FRAMES
Definition qfiles.h:47
#define MD2_MAX_TRIANGLES
Definition qfiles.h:45
#define MD2_MAX_SKINNAME
Definition qfiles.h:49
#define TAG_VERSION
Definition qfiles.h:43
#define MD2_MAX_VERTS
Definition qfiles.h:46
#define MD2_ALIAS_VERSION
Definition qfiles.h:42
#define MD2_MAX_SKINS
Definition qfiles.h:48
QGL_EXTERN int GLboolean GLfloat * v
Definition r_gl.h:120
QGL_EXTERN GLuint index
Definition r_gl.h:110
QGL_EXTERN GLint i
Definition r_gl.h:113
QGL_EXTERN GLuint GLsizei bufSize
Definition r_gl.h:110
local graphics definitions
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
bool R_UseActorSkin(void)
Definition r_model.cpp:342
image_t * R_AliasModelGetSkin(const char *modelFileName, const char *skin)
@ mod_alias_md2
Definition r_model.h:41
bool R_ModLoadMDX(model_t *mod)
Tries to load a mdx file that contains the normals and the tangents for a model.
void R_ModCalcUniqueNormalsAndTangents(mAliasMesh_t *mesh, int nFrames, float smoothness)
Calculates normals and tangents for all frames and does vertex merging based on smoothness.
void R_ModLoadArrayData(mAliasModel_t *mod, mAliasMesh_t *mesh, bool loadNormals)
Allocates data arrays for animated models. Only called once at loading time.
#define MAX_ALIAS_VERTS
#define mAliasCoord_t
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.
static void R_ModLoadTags(model_t *mod, void *buffer, int bufSize)
static void R_ModLoadLevelOfDetailData(model_t *mod, bool loadNormals)
Adds new meshes to md2 models for different level of detail meshes.
void R_ModLoadAliasMD2Model(model_t *mod, byte *buffer, int bufSize, bool loadNormals)
Load MD2 models from file.
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.
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.
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
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
Definition shared.cpp:587
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition shared.cpp:494
These two shorts are used to map a vertex onto a skin The horizontal axis position is given by s,...
Definition qfiles.h:57
is a variable sized structure, however all frame_t structures within the same file will have the same...
Definition qfiles.h:90
dMD2TriangleVertex_t verts[1]
Definition qfiles.h:94
float scale[3]
Definition qfiles.h:91
float translate[3]
Definition qfiles.h:92
the glcmd format: a positive integer starts a tristrip command, followed by that many vertex structur...
Definition qfiles.h:109
uint32_t version
Definition qfiles.h:115
uint32_t ofs_tris
Definition qfiles.h:130
uint32_t skinwidth
Definition qfiles.h:117
uint32_t ofs_st
Definition qfiles.h:129
uint32_t ofs_frames
Definition qfiles.h:131
uint32_t ofs_end
Definition qfiles.h:133
uint32_t num_frames
Definition qfiles.h:126
uint32_t ofs_skins
Definition qfiles.h:128
uint32_t num_tris
Definition qfiles.h:124
uint32_t skinheight
Definition qfiles.h:118
uint32_t num_verts
Definition qfiles.h:122
uint32_t num_skins
Definition qfiles.h:121
uint32_t framesize
Definition qfiles.h:119
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
uint32_t ofs_end
Definition qfiles.h:151
uint32_t ofs_extractend
Definition qfiles.h:152
uint32_t version
Definition qfiles.h:143
uint32_t ofs_names
Definition qfiles.h:149
uint32_t ofs_tags
Definition qfiles.h:150
uint32_t ident
Definition qfiles.h:142
uint32_t num_frames
Definition qfiles.h:146
uint32_t num_tags
Definition qfiles.h:145
char name[MAX_QPATH]
Definition r_image.h:62
mAliasVertex_t * vertexes
int32_t * indexes
mAliasSkin_t * skins
mAliasCoord_t * stcoords
char name[MODEL_MAX_PATH]
int32_t num_indexes
int32_t num_verts
mAliasTag_t * tags
mAliasFrame_t * frames
mAliasMesh_t * meshes
char name[MODEL_MAX_PATH]
image_t * skin
char name[MODEL_MAX_PATH]
mAliasTagOrientation_t * orient
modtype_t type
Definition r_model.h:46
AABB modBox
Definition r_model.h:51
mAliasModel_t alias
Definition r_model.h:63
char name[MAX_QPATH]
Definition r_model.h:44
#define VectorCopy(src, dest)
Definition vector.h:51
#define VectorSet(v, x, y, z)
Definition vector.h:59