Quake II RTX doxygen  1.0 dev
model.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
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 // models.c -- model loading and caching
19 
20 // models are the only shared resource between a client and server running
21 // on the same machine.
22 
23 #include "sw.h"
24 #include "format/md2.h"
25 
27 
28 /*
29 =================
30 ProcessTexinfo
31 =================
32 */
33 static void ProcessTexinfo(bsp_t *bsp)
34 {
35  mtexinfo_t *tex;
36  int i;
37  vec_t len1, len2;
38  char name[MAX_QPATH];
39  imageflags_t flags;
40 
41  tex = bsp->texinfo;
42  for (i = 0; i < bsp->numtexinfo; i++, tex++) {
43  len1 = VectorLength(tex->axis[0]);
44  len2 = VectorLength(tex->axis[1]);
45  len1 = (len1 + len2) / 2;
46  if (len1 < 0.32)
47  tex->mipadjust = 4;
48  else if (len1 < 0.49)
49  tex->mipadjust = 3;
50  else if (len1 < 0.99)
51  tex->mipadjust = 2;
52  else
53  tex->mipadjust = 1;
54 
55  if (tex->c.flags & (SURF_WARP | SURF_FLOWING))
56  flags = IF_TURBULENT;
57  else
58  flags = IF_NONE;
59 
60  Q_concat(name, sizeof(name), "textures/", tex->name, ".wal", NULL);
61  FS_NormalizePath(name, name);
62  tex->image = IMG_Find(name, IT_WALL, flags);
63  }
64 }
65 
66 /*
67 ================
68 CalcSurfaceExtents
69 
70 Fills in s->texturemins[] and s->extents[]
71 ================
72 */
73 static void CalcSurfaceExtents(mface_t *s)
74 {
75  vec_t mins[2], maxs[2], val;
76  int i, j;
77  msurfedge_t *e;
78  mvertex_t *v;
79  mtexinfo_t *tex;
80  int bmins[2], bmaxs[2];
81 
82  mins[0] = mins[1] = 999999;
83  maxs[0] = maxs[1] = -999999;
84 
85  tex = s->texinfo;
86  e = s->firstsurfedge;
87  for (i = 0; i < s->numsurfedges; i++, e++) {
88  v = e->edge->v[e->vert];
89  for (j = 0; j < 2; j++) {
90  val = DotProduct(v->point, tex->axis[j]) + tex->offset[j];
91  if (val < mins[j])
92  mins[j] = val;
93  if (val > maxs[j])
94  maxs[j] = val;
95  }
96  }
97 
98  for (i = 0; i < 2; i++) {
99  bmins[i] = floor(mins[i] / 16);
100  bmaxs[i] = ceil(maxs[i] / 16);
101 
102  s->texturemins[i] = bmins[i] << 4;
103  s->extents[i] = (bmaxs[i] - bmins[i]) << 4;
104  if (s->extents[i] < 16) {
105  s->extents[i] = 16; // take at least one cache block
106  } else if (s->extents[i] > 256) {
107  Com_Error(ERR_DROP, "Bad surface extents");
108  }
109  }
110 }
111 
112 
113 /*
114 =================
115 ProcessFaces
116 =================
117 */
118 static void ProcessFaces(bsp_t *bsp)
119 {
120  mface_t *s;
121  int i, j;
122 
123  s = bsp->faces;
124  for (i = 0; i < bsp->numfaces; i++, s++) {
125  // set the drawing flags
126  if (s->texinfo->c.flags & SURF_SKY) {
127  continue;
128  }
129  if (s->texinfo->c.flags & (SURF_WARP | SURF_FLOWING)) {
130  s->drawflags |= DSURF_TURB;
131  for (j = 0; j < 2; j++) {
132  s->extents[j] = 16384;
133  s->texturemins[j] = -8192;
134  }
135  continue;
136  }
138  }
139 }
140 
141 
142 
143 
144 /*
145 ==============================================================================
146 
147 ALIAS MODELS
148 
149 ==============================================================================
150 */
151 
152 /*
153 =================
154 Mod_LoadAliasModel
155 =================
156 */
157 qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length)
158 {
159  dmd2header_t header;
160  dmd2frame_t *src_frame;
161  //dmd2trivertx_t *src_vert;
162  dmd2triangle_t *src_tri;
163  dmd2stvert_t *src_st;
164  maliasframe_t *dst_frame;
165  //maliasvert_t *dst_vert;
166  maliastri_t *dst_tri;
167  maliasst_t *dst_st;
168  char skinname[MAX_QPATH];
169  char *src_skin;
170  int i, j;
171  qerror_t ret;
172 
173  if (length < sizeof(header)) {
174  return Q_ERR_FILE_TOO_SMALL;
175  }
176 
177  // byte swap the header
178  header = *(dmd2header_t *)rawdata;
179  for (i = 0; i < sizeof(header) / 4; i++) {
180  ((uint32_t *)&header)[i] = LittleLong(((uint32_t *)&header)[i]);
181  }
182 
183  // validate the header
184  ret = MOD_ValidateMD2(&header, length);
185  if (ret) {
186  if (ret == Q_ERR_TOO_FEW) {
187  // empty models draw nothing
188  model->type = MOD_EMPTY;
189  return Q_ERR_SUCCESS;
190  }
191  return ret;
192  }
193 
194  Hunk_Begin(&model->hunk, 0x400000);
195  model->type = MOD_ALIAS;
196 
197  // load triangle indices
198  model->tris = MOD_Malloc(header.num_tris * sizeof(maliastri_t));
199  model->numtris = header.num_tris;
200 
201  src_tri = (dmd2triangle_t *)((byte *)rawdata + header.ofs_tris);
202  dst_tri = model->tris;
203  for (i = 0; i < header.num_tris; i++, src_tri++, dst_tri++) {
204  for (j = 0; j < 3; j++) {
205  uint16_t idx_xyz = LittleShort(src_tri->index_xyz[j]);
206  uint16_t idx_st = LittleShort(src_tri->index_st[j]);
207 
208  if (idx_xyz >= header.num_xyz || idx_st >= header.num_st) {
209  ret = Q_ERR_BAD_INDEX;
210  goto fail;
211  }
212 
213  dst_tri->index_xyz[j] = idx_xyz;
214  dst_tri->index_st[j] = idx_st;
215  }
216  }
217 
218  // load base s and t vertices
219  model->sts = MOD_Malloc(header.num_st * sizeof(maliasst_t));
220  model->numsts = header.num_st;
221  model->skinwidth = header.skinwidth;
222  model->skinheight = header.skinheight;
223 
224  src_st = (dmd2stvert_t *)((byte *)rawdata + header.ofs_st);
225  dst_st = model->sts;
226  for (i = 0; i < header.num_st; i++, src_st++, dst_st++) {
227  dst_st->s = (int16_t)LittleShort(src_st->s);
228  dst_st->t = (int16_t)LittleShort(src_st->t);
229 
230  if (dst_st->s < 0 || dst_st->s >= header.skinwidth) {
231  ret = Q_ERR_BAD_INDEX;
232  goto fail;
233  }
234 
235  if (dst_st->t < 0 || dst_st->t >= header.skinheight) {
236  ret = Q_ERR_BAD_INDEX;
237  goto fail;
238  }
239  }
240 
241  // load the frames
242  model->frames = MOD_Malloc(header.num_frames * sizeof(maliasframe_t));
243  model->numframes = header.num_frames;
244  model->numverts = header.num_xyz;
245 
246  src_frame = (dmd2frame_t *)((byte *)rawdata + header.ofs_frames);
247  dst_frame = model->frames;
248  for (i = 0; i < header.num_frames; i++, dst_frame++) {
249  for (j = 0; j < 3; j++) {
250  dst_frame->scale[j] = LittleFloat(src_frame->scale[j]);
251  dst_frame->translate[j] = LittleFloat(src_frame->translate[j]);
252  }
253 
254  // verts are all 8 bit, so no swapping needed
255  dst_frame->verts = MOD_Malloc(header.num_xyz * sizeof(maliasvert_t));
256  memcpy(dst_frame->verts, src_frame->verts, header.num_xyz * sizeof(maliasvert_t));
257 
258  // check normal indices
259  for (j = 0; j < header.num_xyz; j++) {
260  if (dst_frame->verts[j].lightnormalindex > NUMVERTEXNORMALS) {
261  ret = Q_ERR_BAD_INDEX;
262  goto fail;
263  }
264  }
265 
266  src_frame = (dmd2frame_t *)((byte *)src_frame + header.framesize);
267  }
268 
269  // register all skins
270  src_skin = (char *)rawdata + header.ofs_skins;
271  for (i = 0; i < header.num_skins; i++) {
272  if (!Q_memccpy(skinname, src_skin, 0, sizeof(skinname))) {
273  ret = Q_ERR_STRING_TRUNCATED;
274  goto fail;
275  }
276  FS_NormalizePath(skinname, skinname);
277  model->skins[i] = IMG_Find(skinname, IT_SKIN, IF_NONE);
278  src_skin += MD2_MAX_SKINNAME;
279  }
280  model->numskins = header.num_skins;
281 
282  Hunk_End(&model->hunk);
283  return Q_ERR_SUCCESS;
284 
285 fail:
286  Hunk_Free(&model->hunk);
287  return ret;
288 }
289 
290 void MOD_Reference(model_t *model)
291 {
292  int i;
293 
294  // register any images used by the models
295  switch (model->type) {
296  case MOD_ALIAS:
297  for (i = 0; i < model->numskins; i++) {
298  model->skins[i]->registration_sequence = registration_sequence;
299  }
300  break;
301  case MOD_SPRITE:
302  for (i = 0; i < model->numframes; i++) {
303  model->spriteframes[i].image->registration_sequence = registration_sequence;
304  }
305  break;
306  case MOD_EMPTY:
307  break;
308  default:
309  Com_Error(ERR_FATAL, "%s: bad model type", __func__);
310  }
311 
312  model->registration_sequence = registration_sequence;
313 }
314 
315 /*
316 @@@@@@@@@@@@@@@@@@@@@
317 R_BeginRegistration
318 
319 Specifies the model that will be used as the world
320 @@@@@@@@@@@@@@@@@@@@@
321 */
322 void R_BeginRegistration(const char *model)
323 {
324  char fullname[MAX_QPATH];
325  bsp_t *bsp;
326  qerror_t ret;
327  int i;
328 
330  r_oldviewcluster = -1; // force markleafs
331 
332  D_FlushCaches();
333 
334  Q_concat(fullname, sizeof(fullname), "maps/", model, ".bsp", NULL);
335  ret = BSP_Load(fullname, &bsp);
336  if (!bsp) {
337  Com_Error(ERR_DROP, "%s: couldn't load %s: %s",
338  __func__, fullname, Q_ErrorString(ret));
339  }
340 
341  if (bsp == r_worldmodel) {
342  for (i = 0; i < bsp->numtexinfo; i++) {
343  bsp->texinfo[i].image->registration_sequence = registration_sequence;
344  }
345  bsp->refcount--;
346  return;
347  }
348 
350  r_worldmodel = bsp;
351 
352  ProcessTexinfo(bsp);
353  ProcessFaces(bsp);
354 
355  // TODO
356  R_NewMap();
357 }
358 
359 /*
360 @@@@@@@@@@@@@@@@@@@@@
361 R_EndRegistration
362 
363 @@@@@@@@@@@@@@@@@@@@@
364 */
366 {
367  MOD_FreeUnused();
368  IMG_FreeUnused();
369 }
370 
371 
maliastri_s::index_xyz
unsigned short index_xyz[3]
Definition: sw.h:276
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
maliasst_s
Definition: sw.h:270
Q_ErrorString
const char * Q_ErrorString(qerror_t error)
Definition: error.c:51
registration_sequence
int registration_sequence
Definition: model.c:26
maliastri_s::index_st
unsigned short index_st[3]
Definition: sw.h:277
MOD_Reference
void MOD_Reference(model_t *model)
Definition: model.c:290
MOD_LoadMD2
qerror_t MOD_LoadMD2(model_t *model, const void *rawdata, size_t length)
Definition: model.c:157
R_NewMap
void R_NewMap(void)
Definition: main.c:331
MOD_ValidateMD2
qerror_t MOD_ValidateMD2(dmd2header_t *header, size_t length)
Definition: models.c:142
maliasframe_s::translate
vec3_t translate
Definition: gl.h:227
MOD_FreeUnused
void MOD_FreeUnused(void)
Definition: models.c:105
Hunk_Free
void Hunk_Free(memhunk_t *hunk)
Definition: hunk.c:75
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
BSP_Free
void BSP_Free(bsp_t *bsp)
Definition: bsp.c:932
R_BeginRegistration
void R_BeginRegistration(const char *model)
Definition: model.c:322
sw.h
DSURF_TURB
#define DSURF_TURB
Definition: sw.h:44
Hunk_End
void Hunk_End(memhunk_t *hunk)
Definition: hunk.c:66
maliasst_s::t
signed short t
Definition: sw.h:272
ProcessTexinfo
static void ProcessTexinfo(bsp_t *bsp)
Definition: model.c:33
CalcSurfaceExtents
static void CalcSurfaceExtents(mface_t *s)
Definition: model.c:73
IMG_Find
image_t * IMG_Find(const char *name, imagetype_t type, imageflags_t flags)
Definition: images.c:1122
masliasvert_s
Definition: gl.h:220
D_FlushCaches
void D_FlushCaches(void)
Definition: surf.c:222
maliasst_s::s
signed short s
Definition: sw.h:271
Q_memccpy
void * Q_memccpy(void *dst, const void *src, int c, size_t size)
Definition: shared.c:895
BSP_Load
qerror_t BSP_Load(const char *name, bsp_t **bsp_p)
Definition: bsp.c:1087
IMG_FreeUnused
void IMG_FreeUnused(void)
Definition: images.c:1310
r_oldviewcluster
int r_oldviewcluster
Definition: main.c:74
Q_concat
size_t Q_concat(char *dest, size_t size,...)
Definition: shared.c:758
ProcessFaces
static void ProcessFaces(bsp_t *bsp)
Definition: model.c:118
r_worldmodel
bsp_t * r_worldmodel
Definition: main.c:31
maliasframe_s
Definition: gl.h:225
R_EndRegistration
void R_EndRegistration(void)
Definition: model.c:365
maliasframe_s::verts
maliasvert_t * verts
Definition: sw.h:290
maliastri_s
Definition: sw.h:275
FS_NormalizePath
size_t FS_NormalizePath(char *out, const char *in)
Definition: files.c:331