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