Quake II RTX doxygen  1.0 dev
models.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 2003-2006 Andrey Nazarov
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 #include "gl.h"
20 #include "format/md2.h"
21 #include "format/md3.h"
22 #include "format/sp2.h"
23 
24 #if MAX_ALIAS_VERTS > TESS_MAX_VERTICES
25 #error TESS_MAX_VERTICES
26 #endif
27 
28 #if MD2_MAX_TRIANGLES > TESS_MAX_INDICES / 3
29 #error TESS_MAX_INDICES
30 #endif
31 
32 qerror_t MOD_LoadMD2_GL(model_t *model, const void *rawdata, size_t length)
33 {
34  dmd2header_t header;
35  dmd2frame_t *src_frame;
36  dmd2trivertx_t *src_vert;
37  dmd2triangle_t *src_tri;
38  dmd2stvert_t *src_tc;
39  char *src_skin;
40  maliasframe_t *dst_frame;
41  maliasvert_t *dst_vert;
42  maliasmesh_t *dst_mesh;
43  maliastc_t *dst_tc;
44  int i, j, k, val;
45  uint16_t remap[TESS_MAX_INDICES];
46  uint16_t vertIndices[TESS_MAX_INDICES];
47  uint16_t tcIndices[TESS_MAX_INDICES];
48  uint16_t finalIndices[TESS_MAX_INDICES];
49  int numverts, numindices;
50  char skinname[MAX_QPATH];
51  vec_t scale_s, scale_t;
52  vec3_t mins, maxs;
53  qerror_t ret;
54 
55  if (length < sizeof(header)) {
56  return Q_ERR_FILE_TOO_SMALL;
57  }
58 
59  // byte swap the header
60  header = *(dmd2header_t *)rawdata;
61  for (i = 0; i < sizeof(header) / 4; i++) {
62  ((uint32_t *)&header)[i] = LittleLong(((uint32_t *)&header)[i]);
63  }
64 
65  // validate the header
66  ret = MOD_ValidateMD2(&header, length);
67  if (ret) {
68  if (ret == Q_ERR_TOO_FEW) {
69  // empty models draw nothing
70  model->type = MOD_EMPTY;
71  return Q_ERR_SUCCESS;
72  }
73  return ret;
74  }
75 
76  // load all triangle indices
77  numindices = 0;
78  src_tri = (dmd2triangle_t *)((byte *)rawdata + header.ofs_tris);
79  for (i = 0; i < header.num_tris; i++) {
80  for (j = 0; j < 3; j++) {
81  uint16_t idx_xyz = LittleShort(src_tri->index_xyz[j]);
82  uint16_t idx_st = LittleShort(src_tri->index_st[j]);
83 
84  // some broken models have 0xFFFF indices
85  if (idx_xyz >= header.num_xyz || idx_st >= header.num_st) {
86  break;
87  }
88 
89  vertIndices[numindices + j] = idx_xyz;
90  tcIndices[numindices + j] = idx_st;
91  }
92  if (j == 3) {
93  // only count good triangles
94  numindices += 3;
95  }
96  src_tri++;
97  }
98 
99  if (numindices < 3) {
100  return Q_ERR_TOO_FEW;
101  }
102 
103  for (i = 0; i < numindices; i++) {
104  remap[i] = 0xFFFF;
105  }
106 
107  // remap all triangle indices
108  numverts = 0;
109  src_tc = (dmd2stvert_t *)((byte *)rawdata + header.ofs_st);
110  for (i = 0; i < numindices; i++) {
111  if (remap[i] != 0xFFFF) {
112  continue; // already remapped
113  }
114 
115  for (j = i + 1; j < numindices; j++) {
116  if (vertIndices[i] == vertIndices[j] &&
117  (src_tc[tcIndices[i]].s == src_tc[tcIndices[j]].s &&
118  src_tc[tcIndices[i]].t == src_tc[tcIndices[j]].t)) {
119  // duplicate vertex
120  remap[j] = i;
121  finalIndices[j] = numverts;
122  }
123  }
124 
125  // new vertex
126  remap[i] = i;
127  finalIndices[i] = numverts++;
128  }
129 
130  if (numverts > TESS_MAX_VERTICES) {
131  return Q_ERR_TOO_MANY;
132  }
133 
134  Hunk_Begin(&model->hunk, 0x400000);
135  model->type = MOD_ALIAS;
136  model->nummeshes = 1;
137  model->numframes = header.num_frames;
138  model->meshes = MOD_Malloc(sizeof(maliasmesh_t));
139  model->frames = MOD_Malloc(header.num_frames * sizeof(maliasframe_t));
140 
141  dst_mesh = model->meshes;
142  dst_mesh->numtris = numindices / 3;
143  dst_mesh->numindices = numindices;
144  dst_mesh->numverts = numverts;
145  dst_mesh->numskins = header.num_skins;
146  dst_mesh->verts = MOD_Malloc(numverts * header.num_frames * sizeof(maliasvert_t));
147  dst_mesh->tcoords = MOD_Malloc(numverts * sizeof(maliastc_t));
148  dst_mesh->indices = MOD_Malloc(numindices * sizeof(QGL_INDEX_TYPE));
149 
150  if (dst_mesh->numtris != header.num_tris) {
151  Com_DPrintf("%s has %d bad triangles\n", model->name, header.num_tris - dst_mesh->numtris);
152  }
153 
154  // store final triangle indices
155  for (i = 0; i < numindices; i++) {
156  dst_mesh->indices[i] = finalIndices[i];
157  }
158 
159  // load all skins
160  src_skin = (char *)rawdata + header.ofs_skins;
161  for (i = 0; i < header.num_skins; i++) {
162  if (!Q_memccpy(skinname, src_skin, 0, sizeof(skinname))) {
163  ret = Q_ERR_STRING_TRUNCATED;
164  goto fail;
165  }
166  FS_NormalizePath(skinname, skinname);
167  dst_mesh->skins[i] = IMG_Find(skinname, IT_SKIN, IF_NONE);
168  src_skin += MD2_MAX_SKINNAME;
169  }
170 
171  // load all tcoords
172  src_tc = (dmd2stvert_t *)((byte *)rawdata + header.ofs_st);
173  dst_tc = dst_mesh->tcoords;
174  scale_s = 1.0f / header.skinwidth;
175  scale_t = 1.0f / header.skinheight;
176  for (i = 0; i < numindices; i++) {
177  if (remap[i] != i) {
178  continue;
179  }
180  dst_tc[finalIndices[i]].st[0] =
181  (int16_t)LittleShort(src_tc[tcIndices[i]].s) * scale_s;
182  dst_tc[finalIndices[i]].st[1] =
183  (int16_t)LittleShort(src_tc[tcIndices[i]].t) * scale_t;
184  }
185 
186  // load all frames
187  src_frame = (dmd2frame_t *)((byte *)rawdata + header.ofs_frames);
188  dst_frame = model->frames;
189  for (j = 0; j < header.num_frames; j++) {
190  LittleVector(src_frame->scale, dst_frame->scale);
191  LittleVector(src_frame->translate, dst_frame->translate);
192 
193  // load frame vertices
194  ClearBounds(mins, maxs);
195  for (i = 0; i < numindices; i++) {
196  if (remap[i] != i) {
197  continue;
198  }
199  src_vert = &src_frame->verts[vertIndices[i]];
200  dst_vert = &dst_mesh->verts[j * numverts + finalIndices[i]];
201 
202  dst_vert->pos[0] = src_vert->v[0];
203  dst_vert->pos[1] = src_vert->v[1];
204  dst_vert->pos[2] = src_vert->v[2];
205 
206  val = src_vert->lightnormalindex;
207  if (val >= NUMVERTEXNORMALS) {
208  dst_vert->norm[0] = 0;
209  dst_vert->norm[1] = 0;
210  } else {
211  dst_vert->norm[0] = gl_static.latlngtab[val][0];
212  dst_vert->norm[1] = gl_static.latlngtab[val][1];
213  }
214 
215  for (k = 0; k < 3; k++) {
216  val = dst_vert->pos[k];
217  if (val < mins[k])
218  mins[k] = val;
219  if (val > maxs[k])
220  maxs[k] = val;
221  }
222  }
223 
224  VectorVectorScale(mins, dst_frame->scale, mins);
225  VectorVectorScale(maxs, dst_frame->scale, maxs);
226 
227  dst_frame->radius = RadiusFromBounds(mins, maxs);
228 
229  VectorAdd(mins, dst_frame->translate, dst_frame->bounds[0]);
230  VectorAdd(maxs, dst_frame->translate, dst_frame->bounds[1]);
231 
232  src_frame = (dmd2frame_t *)((byte *)src_frame + header.framesize);
233  dst_frame++;
234  }
235 
236  Hunk_End(&model->hunk);
237  return Q_ERR_SUCCESS;
238 
239 fail:
240  Hunk_Free(&model->hunk);
241  return ret;
242 }
243 
244 #if USE_MD3
245 static qerror_t MOD_LoadMD3Mesh(model_t *model, maliasmesh_t *mesh,
246  const byte *rawdata, size_t length, size_t *offset_p)
247 {
248  dmd3mesh_t header;
249  size_t end;
250  dmd3vertex_t *src_vert;
251  dmd3coord_t *src_tc;
252  dmd3skin_t *src_skin;
253  uint32_t *src_idx;
254  maliasvert_t *dst_vert;
255  maliastc_t *dst_tc;
256  QGL_INDEX_TYPE *dst_idx;
257  uint32_t index;
258  char skinname[MAX_QPATH];
259  int i;
260 
261  if (length < sizeof(header))
262  return Q_ERR_BAD_EXTENT;
263 
264  // byte swap the header
265  header = *(dmd3mesh_t *)rawdata;
266  for (i = 0; i < sizeof(header) / 4; i++)
267  ((uint32_t *)&header)[i] = LittleLong(((uint32_t *)&header)[i]);
268 
269  if (header.meshsize < sizeof(header) || header.meshsize > length)
270  return Q_ERR_BAD_EXTENT;
271  if (header.num_verts < 3)
272  return Q_ERR_TOO_FEW;
273  if (header.num_verts > TESS_MAX_VERTICES)
274  return Q_ERR_TOO_MANY;
275  if (header.num_tris < 1)
276  return Q_ERR_TOO_FEW;
277  if (header.num_tris > TESS_MAX_INDICES / 3)
278  return Q_ERR_TOO_MANY;
279  if (header.num_skins > MAX_ALIAS_SKINS)
280  return Q_ERR_TOO_MANY;
281  end = header.ofs_skins + header.num_skins * sizeof(dmd3skin_t);
282  if (end < header.ofs_skins || end > length)
283  return Q_ERR_BAD_EXTENT;
284  end = header.ofs_verts + header.num_verts * model->numframes * sizeof(dmd3vertex_t);
285  if (end < header.ofs_verts || end > length)
286  return Q_ERR_BAD_EXTENT;
287  end = header.ofs_tcs + header.num_verts * sizeof(dmd3coord_t);
288  if (end < header.ofs_tcs || end > length)
289  return Q_ERR_BAD_EXTENT;
290  end = header.ofs_indexes + header.num_tris * 3 * sizeof(uint32_t);
291  if (end < header.ofs_indexes || end > length)
292  return Q_ERR_BAD_EXTENT;
293 
294  mesh->numtris = header.num_tris;
295  mesh->numindices = header.num_tris * 3;
296  mesh->numverts = header.num_verts;
297  mesh->numskins = header.num_skins;
298  mesh->verts = MOD_Malloc(sizeof(maliasvert_t) * header.num_verts * model->numframes);
299  mesh->tcoords = MOD_Malloc(sizeof(maliastc_t) * header.num_verts);
300  mesh->indices = MOD_Malloc(sizeof(QGL_INDEX_TYPE) * header.num_tris * 3);
301 
302  // load all skins
303  src_skin = (dmd3skin_t *)(rawdata + header.ofs_skins);
304  for (i = 0; i < header.num_skins; i++) {
305  if (!Q_memccpy(skinname, src_skin->name, 0, sizeof(skinname)))
306  return Q_ERR_STRING_TRUNCATED;
307  FS_NormalizePath(skinname, skinname);
308  mesh->skins[i] = IMG_Find(skinname, IT_SKIN, IF_NONE);
309  }
310 
311  // load all vertices
312  src_vert = (dmd3vertex_t *)(rawdata + header.ofs_verts);
313  dst_vert = mesh->verts;
314  for (i = 0; i < header.num_verts * model->numframes; i++) {
315  dst_vert->pos[0] = (int16_t)LittleShort(src_vert->point[0]);
316  dst_vert->pos[1] = (int16_t)LittleShort(src_vert->point[1]);
317  dst_vert->pos[2] = (int16_t)LittleShort(src_vert->point[2]);
318 
319  dst_vert->norm[0] = src_vert->norm[0];
320  dst_vert->norm[1] = src_vert->norm[1];
321 
322  src_vert++; dst_vert++;
323  }
324 
325  // load all texture coords
326  src_tc = (dmd3coord_t *)(rawdata + header.ofs_tcs);
327  dst_tc = mesh->tcoords;
328  for (i = 0; i < header.num_verts; i++) {
329  dst_tc->st[0] = LittleFloat(src_tc->st[0]);
330  dst_tc->st[1] = LittleFloat(src_tc->st[1]);
331  src_tc++; dst_tc++;
332  }
333 
334  // load all triangle indices
335  src_idx = (uint32_t *)(rawdata + header.ofs_indexes);
336  dst_idx = mesh->indices;
337  for (i = 0; i < header.num_tris * 3; i++) {
338  index = LittleLong(*src_idx++);
339  if (index >= header.num_verts)
340  return Q_ERR_BAD_INDEX;
341  *dst_idx++ = index;
342  }
343 
344  *offset_p = header.meshsize;
345  return Q_ERR_SUCCESS;
346 }
347 
348 qerror_t MOD_LoadMD3_GL(model_t *model, const void *rawdata, size_t length)
349 {
350  dmd3header_t header;
351  size_t end, offset, remaining;
352  dmd3frame_t *src_frame;
353  maliasframe_t *dst_frame;
354  const byte *src_mesh;
355  int i;
356  qerror_t ret;
357 
358  if (length < sizeof(header))
359  return Q_ERR_FILE_TOO_SMALL;
360 
361  // byte swap the header
362  header = *(dmd3header_t *)rawdata;
363  for (i = 0; i < sizeof(header) / 4; i++)
364  ((uint32_t *)&header)[i] = LittleLong(((uint32_t *)&header)[i]);
365 
366  if (header.ident != MD3_IDENT)
367  return Q_ERR_UNKNOWN_FORMAT;
368  if (header.version != MD3_VERSION)
369  return Q_ERR_UNKNOWN_FORMAT;
370  if (header.num_frames < 1)
371  return Q_ERR_TOO_FEW;
372  if (header.num_frames > MD3_MAX_FRAMES)
373  return Q_ERR_TOO_MANY;
374  end = header.ofs_frames + sizeof(dmd3frame_t) * header.num_frames;
375  if (end < header.ofs_frames || end > length)
376  return Q_ERR_BAD_EXTENT;
377  if (header.num_meshes < 1)
378  return Q_ERR_TOO_FEW;
379  if (header.num_meshes > MD3_MAX_MESHES)
380  return Q_ERR_TOO_MANY;
381  if (header.ofs_meshes > length)
382  return Q_ERR_BAD_EXTENT;
383 
384  Hunk_Begin(&model->hunk, 0x400000);
385  model->type = MOD_ALIAS;
386  model->numframes = header.num_frames;
387  model->nummeshes = header.num_meshes;
388  model->meshes = MOD_Malloc(sizeof(maliasmesh_t) * header.num_meshes);
389  model->frames = MOD_Malloc(sizeof(maliasframe_t) * header.num_frames);
390 
391  // load all frames
392  src_frame = (dmd3frame_t *)((byte *)rawdata + header.ofs_frames);
393  dst_frame = model->frames;
394  for (i = 0; i < header.num_frames; i++) {
395  LittleVector(src_frame->translate, dst_frame->translate);
396  VectorSet(dst_frame->scale, MD3_XYZ_SCALE, MD3_XYZ_SCALE, MD3_XYZ_SCALE);
397 
398  LittleVector(src_frame->mins, dst_frame->bounds[0]);
399  LittleVector(src_frame->maxs, dst_frame->bounds[1]);
400  dst_frame->radius = LittleFloat(src_frame->radius);
401 
402  src_frame++; dst_frame++;
403  }
404 
405  // load all meshes
406  src_mesh = (const byte *)rawdata + header.ofs_meshes;
407  remaining = length - header.ofs_meshes;
408  for (i = 0; i < header.num_meshes; i++) {
409  ret = MOD_LoadMD3Mesh(model, &model->meshes[i], src_mesh, remaining, &offset);
410  if (ret)
411  goto fail;
412  src_mesh += offset;
413  remaining -= offset;
414  }
415 
416  Hunk_End(&model->hunk);
417  return Q_ERR_SUCCESS;
418 
419 fail:
420  Hunk_Free(&model->hunk);
421  return ret;
422 }
423 #endif
424 
425 void MOD_Reference_GL(model_t *model)
426 {
427  int i, j;
428 
429  // register any images used by the models
430  switch (model->type) {
431  case MOD_ALIAS:
432  for (i = 0; i < model->nummeshes; i++) {
433  maliasmesh_t *mesh = &model->meshes[i];
434  for (j = 0; j < mesh->numskins; j++) {
435  mesh->skins[j]->registration_sequence = registration_sequence;
436  }
437  }
438  break;
439  case MOD_SPRITE:
440  for (i = 0; i < model->numframes; i++) {
441  model->spriteframes[i].image->registration_sequence = registration_sequence;
442  }
443  break;
444  case MOD_EMPTY:
445  break;
446  default:
447  Com_Error(ERR_FATAL, "%s: bad model type", __func__);
448  }
449 
450  model->registration_sequence = registration_sequence;
451 }
452 
RadiusFromBounds
vec_t RadiusFromBounds(const vec3_t mins, const vec3_t maxs)
Definition: shared.c:127
maliasmesh_s
Definition: gl.h:232
TESS_MAX_INDICES
#define TESS_MAX_INDICES
Definition: gl.h:460
maliasmesh_s::numindices
int numindices
Definition: gl.h:235
masliasvert_s::norm
byte norm[2]
Definition: gl.h:222
maliasmesh_s::tcoords
maliastc_t * tcoords
Definition: gl.h:238
maliasframe_s::scale
vec3_t scale
Definition: gl.h:226
Hunk_Begin
void Hunk_Begin(memhunk_t *hunk, size_t maxsize)
Definition: hunk.c:23
MOD_LoadMD3_GL
qerror_t MOD_LoadMD3_GL(model_t *model, const void *rawdata, size_t length)
maliastc_s
Definition: gl.h:216
MOD_ValidateMD2
qerror_t MOD_ValidateMD2(dmd2header_t *header, size_t length)
Definition: models.c:142
maliasmesh_s::indices
QGL_INDEX_TYPE * indices
Definition: gl.h:236
MOD_Reference_GL
void MOD_Reference_GL(model_t *model)
Definition: models.c:425
maliasmesh_s::verts
maliasvert_t * verts
Definition: gl.h:237
masliasvert_s::pos
short pos[3]
Definition: gl.h:221
maliasframe_s::translate
vec3_t translate
Definition: gl.h:227
maliasmesh_s::numverts
int numverts
Definition: gl.h:233
maliasmesh_s::skins
image_t * skins[MAX_ALIAS_SKINS]
Definition: gl.h:239
Hunk_Free
void Hunk_Free(memhunk_t *hunk)
Definition: hunk.c:75
TESS_MAX_VERTICES
#define TESS_MAX_VERTICES
Definition: gl.h:459
maliastc_s::st
float st[2]
Definition: gl.h:217
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
maliasframe_s::bounds
vec3_t bounds[2]
Definition: gl.h:228
maliasframe_s::radius
vec_t radius
Definition: gl.h:229
glStatic_t::latlngtab
byte latlngtab[NUMVERTEXNORMALS][2]
Definition: gl.h:76
ClearBounds
void ClearBounds(vec3_t mins, vec3_t maxs)
Definition: shared.c:91
Hunk_End
void Hunk_End(memhunk_t *hunk)
Definition: hunk.c:66
IMG_Find
image_t * IMG_Find(const char *name, imagetype_t type, imageflags_t flags)
Definition: images.c:1122
gl_static
glStatic_t gl_static
Definition: main.c:28
registration_sequence
int registration_sequence
Definition: main.c:34
masliasvert_s
Definition: gl.h:220
maliasmesh_s::numtris
int numtris
Definition: gl.h:234
gl.h
Q_memccpy
void * Q_memccpy(void *dst, const void *src, int c, size_t size)
Definition: shared.c:895
QGL_INDEX_TYPE
#define QGL_INDEX_TYPE
Definition: gl.h:48
maliasframe_s
Definition: gl.h:225
FS_NormalizePath
size_t FS_NormalizePath(char *out, const char *in)
Definition: files.c:331
maliasmesh_s::numskins
int numskins
Definition: gl.h:240
MOD_LoadMD2_GL
qerror_t MOD_LoadMD2_GL(model_t *model, const void *rawdata, size_t length)
Definition: models.c:32