1 /*
2 model_brush.c
3
4 model loading and caching
5
6 Copyright (C) 1996-1997 Id Software, Inc.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to:
21
22 Free Software Foundation, Inc.
23 59 Temple Place - Suite 330
24 Boston, MA 02111-1307, USA
25
26 */
27 // models are the only shared resource between a client and server running
28 // on the same machine.
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #ifdef HAVE_STRING_H
35 # include <string.h>
36 #endif
37 #ifdef HAVE_STRINGS_H
38 # include <strings.h>
39 #endif
40
41 #include <math.h>
42
43 #include "QF/checksum.h"
44 #include "QF/cvar.h"
45 #include "QF/model.h"
46 #include "QF/qendian.h"
47 #include "QF/quakefs.h"
48 #include "QF/render.h"
49 #include "QF/sys.h"
50 #include "QF/va.h"
51
52 #include "QF/plugin/vid_render.h"
53
54 #include "compat.h"
55
56 byte mod_novis[MAX_MAP_LEAFS / 8];
57
58 VISIBLE cvar_t *gl_sky_divide; //FIXME visibility?
59 VISIBLE int mod_lightmap_bytes = 1; //FIXME should this be visible?
60
61 VISIBLE mleaf_t *
Mod_PointInLeaf(const vec3_t p,model_t * model)62 Mod_PointInLeaf (const vec3_t p, model_t *model)
63 {
64 float d;
65 mnode_t *node;
66 plane_t *plane;
67
68 if (!model || !model->nodes)
69 Sys_Error ("Mod_PointInLeaf: bad model");
70
71 node = model->nodes;
72 while (1) {
73 if (node->contents < 0)
74 return (mleaf_t *) node;
75 plane = node->plane;
76 d = DotProduct (p, plane->normal) - plane->dist;
77 if (d >= 0)
78 node = node->children[0];
79 else
80 node = node->children[1];
81 }
82
83 return NULL; // never reached
84 }
85
86 static inline byte *
Mod_DecompressVis(byte * in,model_t * model)87 Mod_DecompressVis (byte * in, model_t *model)
88 {
89 static byte decompressed[MAX_MAP_LEAFS / 8];
90 byte *out;
91 int row, c;
92
93 row = (model->numleafs + 7) >> 3;
94 out = decompressed;
95
96 if (!in) { // no vis info, so make all visible
97 while (row) {
98 *out++ = 0xff;
99 row--;
100 }
101 return decompressed;
102 }
103
104 do {
105 if (*in) {
106 *out++ = *in++;
107 continue;
108 }
109
110 c = in[1];
111 in += 2;
112 while (c) {
113 *out++ = 0;
114 c--;
115 }
116 } while (out - decompressed < row);
117
118 return decompressed;
119 }
120
121 VISIBLE byte *
Mod_LeafPVS(mleaf_t * leaf,model_t * model)122 Mod_LeafPVS (mleaf_t *leaf, model_t *model)
123 {
124 if (leaf == model->leafs)
125 return mod_novis;
126 return Mod_DecompressVis (leaf->compressed_vis, model);
127 }
128
129 // BRUSHMODEL LOADING =========================================================
130
131 //FIXME SLOW! However, it doesn't seem to be a big issue. Leave alone?
132 static void
mod_unique_miptex_name(texture_t ** textures,texture_t * tx,int ind)133 mod_unique_miptex_name (texture_t **textures, texture_t *tx, int ind)
134 {
135 char name[17];
136 int num = 0, i;
137 const char *tag;
138
139 strncpy (name, tx->name, 16);
140 name[16] = 0;
141 do {
142 for (i = 0; i < ind; i++)
143 if (textures[i] && !strcmp (textures[i]->name, tx->name))
144 break;
145 if (i == ind)
146 break;
147 tag = va ("~%x", num++);
148 strncpy (tx->name, name, 16);
149 if (strlen (name) + strlen (tag) <= 15)
150 strcat (tx->name, tag);
151 else
152 strcpy (tx->name + 15 - strlen (tag), tag);
153 } while (1);
154 }
155
156 static void
Mod_LoadTextures(bsp_t * bsp)157 Mod_LoadTextures (bsp_t *bsp)
158 {
159 dmiptexlump_t *m;
160 int i, j, pixels, num, max, altmax;
161 miptex_t *mt;
162 texture_t *tx, *tx2;
163 texture_t *anims[10], *altanims[10];
164
165 if (!bsp->texdatasize) {
166 loadmodel->textures = NULL;
167 return;
168 }
169 m = (dmiptexlump_t *) bsp->texdata;
170
171 loadmodel->numtextures = m->nummiptex;
172 loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof
173 (*loadmodel->textures), loadname);
174
175 for (i = 0; i < m->nummiptex; i++) {
176 if (m->dataofs[i] == -1)
177 continue;
178 mt = (miptex_t *) ((byte *) m + m->dataofs[i]);
179 mt->width = LittleLong (mt->width);
180 mt->height = LittleLong (mt->height);
181 for (j = 0; j < MIPLEVELS; j++)
182 mt->offsets[j] = LittleLong (mt->offsets[j]);
183
184 if ((mt->width & 15) || (mt->height & 15))
185 Sys_Error ("Texture %s is not 16 aligned", mt->name);
186 pixels = mt->width * mt->height / 64 * 85;
187 tx = Hunk_AllocName (sizeof (texture_t) + pixels, loadname);
188
189 loadmodel->textures[i] = tx;
190
191 memcpy (tx->name, mt->name, sizeof (tx->name));
192 mod_unique_miptex_name (loadmodel->textures, tx, i);
193 tx->width = mt->width;
194 tx->height = mt->height;
195 for (j = 0; j < MIPLEVELS; j++)
196 tx->offsets[j] =
197 mt->offsets[j] + sizeof (texture_t) - sizeof (miptex_t);
198 // the pixels immediately follow the structures
199 memcpy (tx + 1, mt + 1, pixels);
200
201 if (!strncmp (mt->name, "sky", 3))
202 loadmodel->skytexture = tx;
203 if (mod_funcs)
204 mod_funcs->Mod_ProcessTexture (tx);
205 }
206
207 // sequence the animations
208 for (i = 0; i < m->nummiptex; i++) {
209 tx = loadmodel->textures[i];
210 if (!tx || tx->name[0] != '+')
211 continue;
212 if (tx->anim_next)
213 continue; // already sequenced
214
215 // find the number of frames in the animation
216 memset (anims, 0, sizeof (anims));
217 memset (altanims, 0, sizeof (altanims));
218
219 max = tx->name[1];
220 altmax = 0;
221 if (max >= 'a' && max <= 'z')
222 max -= 'a' - 'A';
223 if (max >= '0' && max <= '9') {
224 max -= '0';
225 altmax = 0;
226 anims[max] = tx;
227 max++;
228 } else if (max >= 'A' && max <= 'J') {
229 altmax = max - 'A';
230 max = 0;
231 altanims[altmax] = tx;
232 altmax++;
233 } else
234 Sys_Error ("Bad animating texture %s", tx->name);
235
236 for (j = i + 1; j < m->nummiptex; j++) {
237 tx2 = loadmodel->textures[j];
238 if (!tx2 || tx2->name[0] != '+')
239 continue;
240 if (strcmp (tx2->name + 2, tx->name + 2))
241 continue;
242
243 num = tx2->name[1];
244 if (num >= 'a' && num <= 'z')
245 num -= 'a' - 'A';
246 if (num >= '0' && num <= '9') {
247 num -= '0';
248 anims[num] = tx2;
249 if (num + 1 > max)
250 max = num + 1;
251 } else if (num >= 'A' && num <= 'J') {
252 num = num - 'A';
253 altanims[num] = tx2;
254 if (num + 1 > altmax)
255 altmax = num + 1;
256 } else
257 Sys_Error ("Bad animating texture %s", tx->name);
258 }
259
260 #define ANIM_CYCLE 2
261 // link them all together
262 for (j = 0; j < max; j++) {
263 tx2 = anims[j];
264 if (!tx2)
265 Sys_Error ("Missing frame %i of %s", j, tx->name);
266 tx2->anim_total = max * ANIM_CYCLE;
267 tx2->anim_min = j * ANIM_CYCLE;
268 tx2->anim_max = (j + 1) * ANIM_CYCLE;
269 tx2->anim_next = anims[(j + 1) % max];
270 if (altmax)
271 tx2->alternate_anims = altanims[0];
272 }
273 for (j = 0; j < altmax; j++) {
274 tx2 = altanims[j];
275 if (!tx2)
276 Sys_Error ("Missing frame %i of %s", j, tx->name);
277 tx2->anim_total = altmax * ANIM_CYCLE;
278 tx2->anim_min = j * ANIM_CYCLE;
279 tx2->anim_max = (j + 1) * ANIM_CYCLE;
280 tx2->anim_next = altanims[(j + 1) % altmax];
281 if (max)
282 tx2->alternate_anims = anims[0];
283 }
284 }
285 }
286
287 static void
Mod_LoadVisibility(bsp_t * bsp)288 Mod_LoadVisibility (bsp_t *bsp)
289 {
290 if (!bsp->visdatasize) {
291 loadmodel->visdata = NULL;
292 return;
293 }
294 loadmodel->visdata = Hunk_AllocName (bsp->visdatasize, loadname);
295 memcpy (loadmodel->visdata, bsp->visdata, bsp->visdatasize);
296 }
297
298 static void
Mod_LoadEntities(bsp_t * bsp)299 Mod_LoadEntities (bsp_t *bsp)
300 {
301 if (!bsp->entdatasize) {
302 loadmodel->entities = NULL;
303 return;
304 }
305 loadmodel->entities = Hunk_AllocName (bsp->entdatasize, loadname);
306 memcpy (loadmodel->entities, bsp->entdata, bsp->entdatasize);
307 }
308
309 static void
Mod_LoadVertexes(bsp_t * bsp)310 Mod_LoadVertexes (bsp_t *bsp)
311 {
312 dvertex_t *in;
313 int count, i;
314 mvertex_t *out;
315
316 in = bsp->vertexes;
317 count = bsp->numvertexes;
318 out = Hunk_AllocName (count * sizeof (*out), loadname);
319
320 loadmodel->vertexes = out;
321 loadmodel->numvertexes = count;
322
323 for (i = 0; i < count; i++, in++, out++)
324 VectorCopy (in->point, out->position);
325 }
326
327 static void
Mod_LoadSubmodels(bsp_t * bsp)328 Mod_LoadSubmodels (bsp_t *bsp)
329 {
330 dmodel_t *in, *out;
331 int count, i, j;
332
333 in = bsp->models;
334 count = bsp->nummodels;
335 out = Hunk_AllocName (count * sizeof (*out), loadname);
336
337 loadmodel->submodels = out;
338 loadmodel->numsubmodels = count;
339
340 for (i = 0; i < count; i++, in++, out++) {
341 static vec3_t offset = {1, 1, 1};
342 // spread the mins / maxs by a pixel
343 VectorSubtract (in->mins, offset, out->mins);
344 VectorAdd (in->maxs, offset, out->maxs);
345 VectorCopy (in->origin, out->origin);
346 for (j = 0; j < MAX_MAP_HULLS; j++)
347 out->headnode[j] = in->headnode[j];
348 out->visleafs = in->visleafs;
349 out->firstface = in->firstface;
350 out->numfaces = in->numfaces;
351 }
352
353 out = loadmodel->submodels;
354
355 if (out->visleafs > MAX_MAP_LEAFS) {
356 Sys_Error ("Mod_LoadSubmodels: too many visleafs (%d, max = %d) in %s",
357 out->visleafs, MAX_MAP_LEAFS, loadmodel->name);
358 }
359
360 if (out->visleafs > 8192)
361 Sys_MaskPrintf (SYS_WARN,
362 "%i visleafs exceeds standard limit of 8192.\n",
363 out->visleafs);
364 }
365
366 static void
Mod_LoadEdges(bsp_t * bsp)367 Mod_LoadEdges (bsp_t *bsp)
368 {
369 dedge_t *in;
370 int count, i;
371 medge_t *out;
372
373 in = bsp->edges;
374 count = bsp->numedges;
375 out = Hunk_AllocName ((count + 1) * sizeof (*out), loadname);
376
377 loadmodel->edges = out;
378 loadmodel->numedges = count;
379
380 for (i = 0; i < count; i++, in++, out++) {
381 out->v[0] = in->v[0];
382 out->v[1] = in->v[1];
383 }
384 }
385
386 static void
Mod_LoadTexinfo(bsp_t * bsp)387 Mod_LoadTexinfo (bsp_t *bsp)
388 {
389 float len1, len2;
390 int count, miptex, i, j;
391 mtexinfo_t *out;
392 texinfo_t *in;
393
394 in = bsp->texinfo;
395 count = bsp->numtexinfo;
396 out = Hunk_AllocName (count * sizeof (*out), loadname);
397
398 loadmodel->texinfo = out;
399 loadmodel->numtexinfo = count;
400
401 for (i = 0; i < count; i++, in++, out++) {
402 for (j = 0; j < 4; j++) {
403 out->vecs[0][j] = in->vecs[0][j];
404 out->vecs[1][j] = in->vecs[1][j];
405 }
406 len1 = VectorLength (out->vecs[0]);
407 len2 = VectorLength (out->vecs[1]);
408
409 len1 = (len1 + len2) / 2;
410 if (len1 < 0.32)
411 out->mipadjust = 4;
412 else if (len1 < 0.49)
413 out->mipadjust = 3;
414 else if (len1 < 0.99)
415 out->mipadjust = 2;
416 else
417 out->mipadjust = 1;
418
419 miptex = in->miptex;
420 out->flags = in->flags;
421
422 if (!loadmodel->textures) {
423 out->texture = r_notexture_mip; // checkerboard texture
424 out->flags = 0;
425 } else {
426 if (miptex >= loadmodel->numtextures)
427 Sys_Error ("miptex >= loadmodel->numtextures");
428 out->texture = loadmodel->textures[miptex];
429 if (!out->texture) {
430 out->texture = r_notexture_mip; // texture not found
431 out->flags = 0;
432 }
433 }
434 }
435 }
436
437 /*
438 CalcSurfaceExtents
439
440 Fills in s->texturemins[] and s->extents[]
441 */
442 static void
CalcSurfaceExtents(msurface_t * s)443 CalcSurfaceExtents (msurface_t *s)
444 {
445 float mins[2], maxs[2], val;
446 int e, i, j;
447 int bmins[2], bmaxs[2];
448 mtexinfo_t *tex;
449 mvertex_t *v;
450
451 mins[0] = mins[1] = 999999;
452 maxs[0] = maxs[1] = -99999;
453
454 tex = s->texinfo;
455
456 for (i = 0; i < s->numedges; i++) {
457 e = loadmodel->surfedges[s->firstedge + i];
458 if (e >= 0)
459 v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
460 else
461 v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
462
463 for (j = 0; j < 2; j++) {
464 val = v->position[0] * tex->vecs[j][0] +
465 v->position[1] * tex->vecs[j][1] +
466 v->position[2] * tex->vecs[j][2] + tex->vecs[j][3];
467 if (val < mins[j])
468 mins[j] = val;
469 if (val > maxs[j])
470 maxs[j] = val;
471 }
472 }
473
474 for (i = 0; i < 2; i++) {
475 bmins[i] = floor (mins[i] / 16);
476 bmaxs[i] = ceil (maxs[i] / 16);
477
478 s->texturemins[i] = bmins[i] * 16;
479 s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
480 // FIXME even 2000 is really too small, need a saner test
481 if (!(tex->flags & TEX_SPECIAL) && s->extents[i] > 2000)
482 Sys_Error ("Bad surface extents: %d %x %d %d", i, tex->flags,
483 s->extents[i], LongSwap (s->extents[i]));
484 }
485 }
486
487 static void
Mod_LoadFaces(bsp_t * bsp)488 Mod_LoadFaces (bsp_t *bsp)
489 {
490 dface_t *in;
491 int count, planenum, side, surfnum, i;
492 msurface_t *out;
493
494 in = bsp->faces;
495 count = bsp->numfaces;
496 out = Hunk_AllocName (count * sizeof (*out), loadname);
497
498 if (count > 32767) {
499 Sys_MaskPrintf (SYS_WARN,
500 "%i faces exceeds standard limit of 32767.\n", count);
501 }
502
503 loadmodel->surfaces = out;
504 loadmodel->numsurfaces = count;
505
506 for (surfnum = 0; surfnum < count; surfnum++, in++, out++) {
507 out->firstedge = in->firstedge;
508 out->numedges = in->numedges;
509 out->flags = 0;
510
511 planenum = in->planenum;
512 side = in->side;
513 if (side)
514 out->flags |= SURF_PLANEBACK;
515
516 out->plane = loadmodel->planes + planenum;
517
518 out->texinfo = loadmodel->texinfo + in->texinfo;
519
520 CalcSurfaceExtents (out);
521
522 // lighting info
523
524 for (i = 0; i < MAXLIGHTMAPS; i++)
525 out->styles[i] = in->styles[i];
526 i = in->lightofs;
527 if (i == -1)
528 out->samples = NULL;
529 else
530 out->samples = loadmodel->lightdata + (i * mod_lightmap_bytes);
531
532 // set the drawing flags flag
533 if (!out->texinfo->texture || !out->texinfo->texture->name)
534 continue; // avoid crashing on null textures
535
536 if (!strncmp (out->texinfo->texture->name, "sky", 3)) { // sky
537 out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
538 if (gl_sky_divide && gl_sky_divide->int_val)
539 if (mod_funcs)
540 mod_funcs->Mod_SubdivideSurface (out);
541 continue;
542 }
543
544 if (out->texinfo->texture->name[0] == '*') { // turbulent
545 out->flags |= (SURF_DRAWTURB
546 | SURF_DRAWTILED
547 | SURF_LIGHTBOTHSIDES);
548 for (i = 0; i < 2; i++) {
549 out->extents[i] = 16384;
550 out->texturemins[i] = -8192;
551 }
552 if (mod_funcs) // cut up polygon for warps
553 mod_funcs->Mod_SubdivideSurface (out);
554 continue;
555 }
556 }
557 }
558
559 static void
Mod_SetParent(mnode_t * node,mnode_t * parent)560 Mod_SetParent (mnode_t *node, mnode_t *parent)
561 {
562 node->parent = parent;
563 if (node->contents < 0)
564 return;
565 Mod_SetParent (node->children[0], node);
566 Mod_SetParent (node->children[1], node);
567 }
568
569 static void
Mod_LoadNodes(bsp_t * bsp)570 Mod_LoadNodes (bsp_t *bsp)
571 {
572 dnode_t *in;
573 int count, i, j, p;
574 mnode_t *out;
575
576 in = bsp->nodes;
577 count = bsp->numnodes;
578 out = Hunk_AllocName (count * sizeof (*out), loadname);
579
580 if (count > 32767) {
581 Sys_MaskPrintf (SYS_WARN,
582 "%i nodes exceeds standard limit of 32767.\n", count);
583 }
584
585 loadmodel->nodes = out;
586 loadmodel->numnodes = count;
587
588 for (i = 0; i < count; i++, in++, out++) {
589 for (j = 0; j < 3; j++) {
590 out->minmaxs[j] = in->mins[j];
591 out->minmaxs[3 + j] = in->maxs[j];
592 }
593
594 p = in->planenum;
595 out->plane = loadmodel->planes + p;
596
597 out->firstsurface = in->firstface;
598 out->numsurfaces = in->numfaces;
599
600 for (j = 0; j < 2; j++) {
601 p = in->children[j];
602 // this check is for extended bsp 29 files
603 if (p >= 0) {
604 out->children[j] = loadmodel->nodes + p;
605 } else {
606 p = ~p;
607 if (p < loadmodel->numleafs) {
608 out->children[j] = (mnode_t *) (loadmodel->leafs + p);
609 } else {
610 Sys_Printf ("Mod_LoadNodes: invalid leaf index %i "
611 "(file has only %i leafs)\n", p,
612 loadmodel->numleafs);
613 //map it to the solid leaf
614 out->children[j] = (mnode_t *)(loadmodel->leafs);
615 }
616 }
617 }
618 }
619
620 Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
621 }
622
623 static void
Mod_LoadLeafs(bsp_t * bsp)624 Mod_LoadLeafs (bsp_t *bsp)
625 {
626 dleaf_t *in;
627 int count, i, j, p;
628 mleaf_t *out;
629 qboolean isnotmap = true;
630
631 in = bsp->leafs;
632 count = bsp->numleafs;
633 out = Hunk_AllocName (count * sizeof (*out), loadname);
634
635 loadmodel->leafs = out;
636 loadmodel->numleafs = count;
637 // snprintf(s, sizeof (s), "maps/%s.bsp",
638 // Info_ValueForKey(cl.serverinfo,"map"));
639 if (!strncmp ("maps/", loadmodel->name, 5))
640 isnotmap = false;
641 for (i = 0; i < count; i++, in++, out++) {
642 for (j = 0; j < 3; j++) {
643 out->mins[j] = in->mins[j];
644 out->maxs[j] = in->maxs[j];
645 }
646
647 p = in->contents;
648 out->contents = p;
649
650 out->firstmarksurface = loadmodel->marksurfaces + in->firstmarksurface;
651 out->nummarksurfaces = in->nummarksurfaces;
652
653 p = in->visofs;
654 if (p == -1)
655 out->compressed_vis = NULL;
656 else
657 out->compressed_vis = loadmodel->visdata + p;
658 out->efrags = NULL;
659
660 for (j = 0; j < 4; j++)
661 out->ambient_sound_level[j] = in->ambient_level[j];
662
663 // gl underwater warp
664 if (out->contents != CONTENTS_EMPTY) {
665 for (j = 0; j < out->nummarksurfaces; j++)
666 out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
667 }
668 if (isnotmap) {
669 for (j = 0; j < out->nummarksurfaces; j++)
670 out->firstmarksurface[j]->flags |= SURF_DONTWARP;
671 }
672 }
673 }
674
675 static void
Mod_LoadClipnodes(bsp_t * bsp)676 Mod_LoadClipnodes (bsp_t *bsp)
677 {
678 dclipnode_t *in;
679 mclipnode_t *out;
680 hull_t *hull;
681 int count, i;
682
683 in = bsp->clipnodes;
684 count = bsp->numclipnodes;
685 out = Hunk_AllocName (count * sizeof (*out), loadname);
686
687 if (count > 32767) {
688 Sys_MaskPrintf (SYS_WARN,
689 "%i clilpnodes exceeds standard limit of 32767.\n",
690 count);
691 }
692
693 loadmodel->clipnodes = out;
694 loadmodel->numclipnodes = count;
695
696 hull = &loadmodel->hulls[1];
697 loadmodel->hull_list[1] = hull;
698 hull->clipnodes = out;
699 hull->firstclipnode = 0;
700 hull->lastclipnode = count - 1;
701 hull->planes = loadmodel->planes;
702 hull->clip_mins[0] = -16;
703 hull->clip_mins[1] = -16;
704 hull->clip_mins[2] = -24;
705 hull->clip_maxs[0] = 16;
706 hull->clip_maxs[1] = 16;
707 hull->clip_maxs[2] = 32;
708
709 hull = &loadmodel->hulls[2];
710 loadmodel->hull_list[2] = hull;
711 hull->clipnodes = out;
712 hull->firstclipnode = 0;
713 hull->lastclipnode = count - 1;
714 hull->planes = loadmodel->planes;
715 hull->clip_mins[0] = -32;
716 hull->clip_mins[1] = -32;
717 hull->clip_mins[2] = -24;
718 hull->clip_maxs[0] = 32;
719 hull->clip_maxs[1] = 32;
720 hull->clip_maxs[2] = 64;
721
722 for (i = 0; i < count; i++, out++, in++) {
723 out->planenum = in->planenum;
724 if (out->planenum < 0 || out->planenum >= loadmodel->numplanes)
725 Sys_Error ("Mod_LoadClipnodes: planenum out of bounds");
726 out->children[0] = in->children[0];
727 out->children[1] = in->children[1];
728 // these checks are for extended bsp 29 files
729 if (out->children[0] >= count)
730 out->children[0] -= 65536;
731 if (out->children[1] >= count)
732 out->children[1] -= 65536;
733 if ((out->children[0] >= 0
734 && (out->children[0] < hull->firstclipnode
735 || out->children[0] > hull->lastclipnode))
736 || (out->children[1] >= 0
737 && (out->children[1] < hull->firstclipnode
738 || out->children[1] > hull->lastclipnode)))
739 Sys_Error ("Mod_LoadClipnodes: bad node number");
740 }
741 }
742
743 /*
744 Mod_MakeHull0
745
746 Replicate the drawing hull structure as a clipping hull
747 */
748 static void
Mod_MakeHull0(void)749 Mod_MakeHull0 (void)
750 {
751 mclipnode_t *out;
752 hull_t *hull;
753 int count, i, j;
754 mnode_t *in, *child;
755
756 hull = &loadmodel->hulls[0];
757 loadmodel->hull_list[0] = hull;
758
759 in = loadmodel->nodes;
760 count = loadmodel->numnodes;
761 out = Hunk_AllocName (count * sizeof (*out), loadname);
762
763 hull->clipnodes = out;
764 hull->firstclipnode = 0;
765 hull->lastclipnode = count - 1;
766 hull->planes = loadmodel->planes;
767
768 for (i = 0; i < count; i++, out++, in++) {
769 out->planenum = in->plane - loadmodel->planes;
770 for (j = 0; j < 2; j++) {
771 child = in->children[j];
772 if (child->contents < 0)
773 out->children[j] = child->contents;
774 else
775 out->children[j] = child - loadmodel->nodes;
776 }
777 }
778 }
779
780 static void
Mod_LoadMarksurfaces(bsp_t * bsp)781 Mod_LoadMarksurfaces (bsp_t *bsp)
782 {
783 int count, i, j;
784 msurface_t **out;
785 uint32_t *in;
786
787 in = bsp->marksurfaces;
788 count = bsp->nummarksurfaces;
789 out = Hunk_AllocName (count * sizeof (*out), loadname);
790
791 if (count > 32767) {
792 Sys_MaskPrintf (SYS_WARN,
793 "%i marksurfaces exceeds standard limit of 32767.\n",
794 count);
795 }
796
797 loadmodel->marksurfaces = out;
798 loadmodel->nummarksurfaces = count;
799
800 for (i = 0; i < count; i++) {
801 j = in[i];
802 if (j >= loadmodel->numsurfaces)
803 Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
804 out[i] = loadmodel->surfaces + j;
805 }
806 }
807
808 static void
Mod_LoadSurfedges(bsp_t * bsp)809 Mod_LoadSurfedges (bsp_t *bsp)
810 {
811 int count, i;
812 int32_t *in;
813 int *out;
814
815 in = bsp->surfedges;
816 count = bsp->numsurfedges;
817 out = Hunk_AllocName (count * sizeof (*out), loadname);
818
819 loadmodel->surfedges = out;
820 loadmodel->numsurfedges = count;
821
822 for (i = 0; i < count; i++)
823 out[i] = in[i];
824 }
825
826 static void
Mod_LoadPlanes(bsp_t * bsp)827 Mod_LoadPlanes (bsp_t *bsp)
828 {
829 dplane_t *in;
830 int bits, count, i, j;
831 plane_t *out;
832
833 in = bsp->planes;
834 count = bsp->numplanes;
835 out = Hunk_AllocName (count * 2 * sizeof (*out), loadname);
836
837 loadmodel->planes = out;
838 loadmodel->numplanes = count;
839
840 for (i = 0; i < count; i++, in++, out++) {
841 bits = 0;
842 for (j = 0; j < 3; j++) {
843 out->normal[j] = in->normal[j];
844 if (out->normal[j] < 0)
845 bits |= 1 << j;
846 }
847
848 out->dist = in->dist;
849 out->type = in->type;
850 out->signbits = bits;
851 }
852 }
853
854 static void
do_checksums(const bsp_t * bsp,void * _mod)855 do_checksums (const bsp_t *bsp, void *_mod)
856 {
857 int i;
858 model_t *mod = (model_t *) _mod;
859 byte *base;
860
861 base = (byte *) bsp->header;
862
863 // checksum all of the map, except for entities
864 mod->checksum = 0;
865 mod->checksum2 = 0;
866 for (i = 0; i < HEADER_LUMPS; i++) {
867 lump_t *lump = bsp->header->lumps + i;
868 int csum;
869
870 if (i == LUMP_ENTITIES)
871 continue;
872 csum = Com_BlockChecksum (base + lump->fileofs, lump->filelen);
873 mod->checksum ^= csum;
874
875 if (i != LUMP_VISIBILITY && i != LUMP_LEAFS && i != LUMP_NODES)
876 mod->checksum2 ^= csum;
877 }
878 }
879
880 static void
recurse_draw_tree(mnode_t * node,int depth)881 recurse_draw_tree (mnode_t *node, int depth)
882 {
883 if (!node || node->contents < 0) {
884 if (depth > loadmodel->depth)
885 loadmodel->depth = depth;
886 return;
887 }
888 recurse_draw_tree (node->children[0], depth + 1);
889 recurse_draw_tree (node->children[1], depth + 1);
890 }
891
892 static void
Mod_FindDrawDepth(void)893 Mod_FindDrawDepth (void)
894 {
895 loadmodel->depth = 0;
896 recurse_draw_tree (loadmodel->nodes, 1);
897 }
898
899 void
Mod_LoadBrushModel(model_t * mod,void * buffer)900 Mod_LoadBrushModel (model_t *mod, void *buffer)
901 {
902 dmodel_t *bm;
903 int i, j;
904 bsp_t *bsp;
905
906 loadmodel->type = mod_brush;
907
908 bsp = LoadBSPMem (buffer, qfs_filesize, do_checksums, mod);
909
910 // load into heap
911 Mod_LoadVertexes (bsp);
912 Mod_LoadEdges (bsp);
913 Mod_LoadSurfedges (bsp);
914 Mod_LoadTextures (bsp);
915 if (mod_funcs)
916 mod_funcs->Mod_LoadLighting (bsp);
917 Mod_LoadPlanes (bsp);
918 Mod_LoadTexinfo (bsp);
919 Mod_LoadFaces (bsp);
920 Mod_LoadMarksurfaces (bsp);
921 Mod_LoadVisibility (bsp);
922 Mod_LoadLeafs (bsp);
923 Mod_LoadNodes (bsp);
924 Mod_LoadClipnodes (bsp);
925 Mod_LoadEntities (bsp);
926 Mod_LoadSubmodels (bsp);
927
928 BSP_Free(bsp);
929
930 Mod_MakeHull0 ();
931
932 Mod_FindDrawDepth ();
933 for (i = 0; i < MAX_MAP_HULLS; i++)
934 Mod_FindClipDepth (&mod->hulls[i]);
935
936 mod->numframes = 2; // regular and alternate animation
937
938 // set up the submodels (FIXME: this is confusing)
939 for (i = 0; i < mod->numsubmodels; i++) {
940 bm = &mod->submodels[i];
941
942 mod->hulls[0].firstclipnode = bm->headnode[0];
943 mod->hull_list[0] = &mod->hulls[0];
944 for (j = 1; j < MAX_MAP_HULLS; j++) {
945 mod->hulls[j].firstclipnode = bm->headnode[j];
946 mod->hulls[j].lastclipnode = mod->numclipnodes - 1;
947 mod->hull_list[j] = &mod->hulls[j];
948 }
949
950 mod->firstmodelsurface = bm->firstface;
951 mod->nummodelsurfaces = bm->numfaces;
952
953 VectorCopy (bm->maxs, mod->maxs);
954 VectorCopy (bm->mins, mod->mins);
955
956 mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
957
958 mod->numleafs = bm->visleafs;
959
960 if (i < mod->numsubmodels - 1) {
961 // duplicate the basic information
962 char name[10];
963
964 snprintf (name, sizeof (name), "*%i", i + 1);
965 loadmodel = Mod_FindName (name);
966 *loadmodel = *mod;
967 strcpy (loadmodel->name, name);
968 mod = loadmodel;
969 }
970 }
971 }
972