Quake II RTX doxygen  1.0 dev
models.c File Reference
#include "gl.h"
#include "format/md2.h"
#include "format/md3.h"
#include "format/sp2.h"

Go to the source code of this file.

Functions

qerror_t MOD_LoadMD2_GL (model_t *model, const void *rawdata, size_t length)
 
void MOD_Reference_GL (model_t *model)
 

Function Documentation

◆ MOD_LoadMD2_GL()

qerror_t MOD_LoadMD2_GL ( model_t *  model,
const void rawdata,
size_t  length 
)

Definition at line 32 of file models.c.

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 }

Referenced by R_RegisterFunctionsGL().

◆ MOD_Reference_GL()

void MOD_Reference_GL ( model_t *  model)

Definition at line 425 of file models.c.

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 }

Referenced by R_RegisterFunctionsGL().

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
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
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
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