1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (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.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 */
20 // models.c -- model loading and caching
21 
22 // models are the only shared resource between a client and server running
23 // on the same machine.
24 
25 #include <float.h>
26 #include <stdint.h>
27 
28 #include "cmd.h"
29 #include "common.h"
30 #include "console.h"
31 #include "model.h"
32 
33 #ifdef SERVERONLY
34 #include "qwsvdef.h"
35 /* A dummy texture to point to. FIXME - should server care about textures? */
36 static texture_t r_notexture_mip_qwsv;
37 #else
38 #include "quakedef.h"
39 #include "render.h"
40 #include "sys.h"
41 #ifdef QW_HACK
42 #include "crc.h"
43 #endif
44 /* FIXME - quick hack to enable merging of NQ/QWSV shared code */
45 #define SV_Error Sys_Error
46 #endif
47 
48 static model_t *loadmodel;
49 static char loadname[MAX_QPATH];	/* for hunk tags */
50 
51 static void Mod_LoadBrushModel(model_t *mod, void *buffer, unsigned long size);
52 static model_t *Mod_LoadModel(model_t *mod, qboolean crash);
53 
54 #define MAX_MOD_KNOWN 512
55 static model_t mod_known[MAX_MOD_KNOWN];
56 static int mod_numknown;
57 
58 static const model_loader_t *mod_loader;
59 
60 static void PVSCache_f(void);
61 
62 // leilei HACK
63 
64 int coloredlights = 0; // to debug the colored lights as we have no menu option yet.
65 
66 
67 /*
68 ===============
69 Mod_Init
70 ===============
71 */
72 void
Mod_Init(const model_loader_t * loader)73 Mod_Init(const model_loader_t *loader)
74 {
75     Cmd_AddCommand("pvscache", PVSCache_f);
76     mod_loader = loader;
77 }
78 
79 /*
80 ===============
81 Mod_PointInLeaf
82 ===============
83 */
Mod_PointInLeaf(const model_t * model,const vec3_t point)84 mleaf_t * Mod_PointInLeaf(const model_t *model, const vec3_t point)
85 {
86    mnode_t *node;
87 
88    if (!model || !model->nodes)
89       SV_Error("%s: bad model", __func__);
90 
91    node = model->nodes;
92 
93    while (1)
94    {
95       float dist;
96       mplane_t *plane;
97       if (node->contents < 0)
98          return (mleaf_t *)node;
99       plane = node->plane;
100       dist = DotProduct(point, plane->normal) - plane->dist;
101       if (dist > 0)
102          node = node->children[0];
103       else
104          node = node->children[1];
105    }
106 
107    return NULL;		// never reached
108 }
109 
110 void
Mod_AddLeafBits(leafbits_t * dst,const leafbits_t * src)111 Mod_AddLeafBits(leafbits_t *dst, const leafbits_t *src)
112 {
113     int i, leafblocks;
114     const leafblock_t *srcblock;
115     leafblock_t *dstblock;
116 
117     if (src->numleafs != dst->numleafs)
118 	SV_Error("%s: src->numleafs (%d) != dst->numleafs (%d)",
119 		 __func__, src->numleafs, dst->numleafs);
120 
121     srcblock = src->bits;
122     dstblock = dst->bits;
123     leafblocks = (src->numleafs + LEAFMASK) >> LEAFSHIFT;
124     for (i = 0; i < leafblocks; i++)
125 	*dstblock++ |= *srcblock++;
126 }
127 
128 #ifdef SERVERONLY
129 int
Mod_CountLeafBits(const leafbits_t * leafbits)130 Mod_CountLeafBits(const leafbits_t *leafbits)
131 {
132     int i, leafblocks, count;
133     leafblock_t block;
134 
135     count = 0;
136     leafblocks = (leafbits->numleafs + LEAFMASK) >> LEAFSHIFT;
137     for (i = 0; i < leafblocks; i++) {
138 	block = leafbits->bits[i];
139 	while (block) {
140 	    count++;
141 	    block &= (block - 1); /* remove least significant bit */
142 	}
143     }
144 
145     return count;
146 };
147 #endif
148 
149 /*
150  * Simple LRU cache for decompressed vis data
151  */
152 typedef struct {
153     const model_t *model;
154     const mleaf_t *leaf;
155     leafbits_t *leafbits;
156 } pvscache_t;
157 static pvscache_t pvscache[2];
158 static leafbits_t *fatpvs;
159 static int pvscache_numleafs;
160 static int pvscache_bytes;
161 static int pvscache_blocks;
162 
163 static int c_cachehit, c_cachemiss;
164 
165 #define PVSCACHE_SIZE ARRAY_SIZE(pvscache)
166 
167 static void
Mod_InitPVSCache(int numleafs)168 Mod_InitPVSCache(int numleafs)
169 {
170     int i;
171     int memsize;
172     byte *leafmem;
173 
174     pvscache_numleafs = numleafs;
175     pvscache_bytes = ((numleafs + LEAFMASK) & ~LEAFMASK) >> 3;
176     pvscache_blocks = pvscache_bytes / sizeof(leafblock_t);
177     memsize = Mod_LeafbitsSize(numleafs);
178     fatpvs = (leafbits_t*)Hunk_AllocName(memsize, "fatpvs");
179 
180     memset(pvscache, 0, sizeof(pvscache));
181     leafmem = (byte*)Hunk_AllocName(PVSCACHE_SIZE * memsize, "pvscache");
182     for (i = 0; i < PVSCACHE_SIZE; i++)
183 	pvscache[i].leafbits = (leafbits_t *)(leafmem + i * memsize);
184 }
185 
186 /*
187 ===================
188 Mod_DecompressVis
189 ===================
190 */
191 
192 static void
Mod_DecompressVis(const byte * in,const model_t * model,leafbits_t * dest)193 Mod_DecompressVis(const byte *in, const model_t *model, leafbits_t *dest)
194 {
195     leafblock_t *out;
196     int num_out;
197     int shift;
198     int count;
199 
200     dest->numleafs = model->numleafs;
201     out = dest->bits;
202 
203     if (!in) {
204 	/* no vis info, so make all visible */
205 	memset(out, 0xff, pvscache_bytes);
206 	return;
207     }
208 
209     memset(out, 0, pvscache_bytes);
210     num_out = 0;
211     shift = 0;
212     do {
213 	if (*in) {
214 	    *out |= (leafblock_t)*in++ << shift;
215 	    shift += 8;
216 	    num_out += 8;
217 	    if (shift == (1 << LEAFSHIFT)) {
218 		shift = 0;
219 		out++;
220 	    }
221 	    continue;
222 	}
223 
224 	/* Run of zeros - skip over */
225 	count = in[1];
226 	in += 2;
227 	out += count / sizeof(leafblock_t);
228 	shift += (count % sizeof(leafblock_t)) << 3;
229 	num_out += count << 3;
230 	if (shift >= (1 << LEAFSHIFT)) {
231 	    shift -= (1 << LEAFSHIFT);
232 	    out++;
233 	}
234     } while (num_out < dest->numleafs);
235 }
236 
237 const leafbits_t *
Mod_LeafPVS(const model_t * model,const mleaf_t * leaf)238 Mod_LeafPVS(const model_t *model, const mleaf_t *leaf)
239 {
240     int slot;
241     pvscache_t tmp;
242 
243     for (slot = 0; slot < PVSCACHE_SIZE; slot++)
244 	if (pvscache[slot].model == model && pvscache[slot].leaf == leaf) {
245 	    c_cachehit++;
246 	    break;
247 	}
248 
249     if (slot) {
250 	if (slot == PVSCACHE_SIZE) {
251 	    slot--;
252 	    tmp.model = model;
253 	    tmp.leaf = leaf;
254 	    tmp.leafbits = pvscache[slot].leafbits;
255 	    if (leaf == model->leafs) {
256 		/* return set with everything visible */
257 		tmp.leafbits->numleafs = model->numleafs;
258 		memset(tmp.leafbits->bits, 0xff, pvscache_bytes);
259 	    } else {
260 		Mod_DecompressVis(leaf->compressed_vis, model, tmp.leafbits);
261 	    }
262 	    c_cachemiss++;
263 	} else {
264 	    tmp = pvscache[slot];
265 	}
266 	memmove(pvscache + 1, pvscache, slot * sizeof(pvscache_t));
267 	pvscache[0] = tmp;
268     }
269 
270     return pvscache[0].leafbits;
271 }
272 
273 static void
PVSCache_f(void)274 PVSCache_f(void)
275 {
276     Con_Printf("PVSCache: %7d hits %7d misses\n", c_cachehit, c_cachemiss);
277 }
278 
Mod_AddToFatPVS(const model_t * model,const vec3_t point,const mnode_t * node)279 static void Mod_AddToFatPVS(const model_t *model, const vec3_t point, const mnode_t *node)
280 {
281    while (1)
282    {
283       float d;
284       mplane_t *plane;
285 
286       /* if this is a leaf, accumulate the pvs bits */
287       if (node->contents < 0)
288       {
289          if (node->contents != CONTENTS_SOLID)
290          {
291             const leafbits_t *pvs = Mod_LeafPVS(model, (const mleaf_t *)node);
292             Mod_AddLeafBits(fatpvs, pvs);
293          }
294          return;
295       }
296 
297       plane = node->plane;
298       d = DotProduct(point, plane->normal) - plane->dist;
299 
300       if (d > 8)
301          node = node->children[0];
302       else if (d < -8)
303          node = node->children[1];
304       else
305       {			// go down both
306          Mod_AddToFatPVS(model, point, node->children[0]);
307          node = node->children[1];
308       }
309    }
310 }
311 
312 /*
313 =============
314 Mod_FatPVS
315 
316 Calculates a PVS that is the inclusive or of all leafs within 8 pixels of the
317 given point.
318 
319 The FatPVS must include a small area around the client to allow head bobbing
320 or other small motion on the client side.  Otherwise, a bob might cause an
321 entity that should be visible to not show up, especially when the bob
322 crosses a waterline.
323 =============
324 */
325 const leafbits_t *
Mod_FatPVS(const model_t * model,const vec3_t point)326 Mod_FatPVS(const model_t *model, const vec3_t point)
327 {
328     fatpvs->numleafs = model->numleafs;
329     memset(fatpvs->bits, 0, pvscache_bytes);
330     Mod_AddToFatPVS(model, point, model->nodes);
331 
332     return fatpvs;
333 }
334 
335 /*
336 ===================
337 Mod_ClearAll
338 ===================
339 */
340 void
Mod_ClearAll(void)341 Mod_ClearAll(void)
342 {
343     int i;
344     model_t *mod;
345 
346     for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++) {
347 	if (mod->type != mod_alias)
348 	    mod->needload = true;
349 	/*
350 	 * FIXME: sprites use the cache data pointer for their own purposes,
351 	 *        bypassing the Cache_Alloc/Free functions.
352 	 */
353 	if (mod->type == mod_sprite)
354 	    mod->cache.data = NULL;
355     }
356 
357     fatpvs = NULL;
358     memset(pvscache, 0, sizeof(pvscache));
359     pvscache_numleafs = 0;
360     pvscache_bytes = pvscache_blocks = 0;
361     c_cachehit = c_cachemiss = 0;
362 }
363 
364 /*
365 ==================
366 Mod_FindName
367 
368 ==================
369 */
370 static model_t *
Mod_FindName(const char * name)371 Mod_FindName(const char *name)
372 {
373     int i;
374     model_t *mod;
375 
376     if (!name[0])
377 	SV_Error("%s: NULL name", __func__);
378 
379 //
380 // search the currently loaded models
381 //
382     for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
383 	if (!strcmp(mod->name, name))
384 	    break;
385 
386     if (i == mod_numknown) {
387 	if (mod_numknown == MAX_MOD_KNOWN)
388 	    SV_Error("mod_numknown == MAX_MOD_KNOWN");
389 	strncpy(mod->name, name, MAX_QPATH - 1);
390 	mod->name[MAX_QPATH - 1] = 0;
391 	mod->needload = true;
392 	mod_numknown++;
393     }
394 
395     return mod;
396 }
397 
398 /*
399 ==================
400 Mod_LoadModel
401 
402 Loads a model into the cache
403 ==================
404 */
405 static model_t *
Mod_LoadModel(model_t * mod,qboolean crash)406 Mod_LoadModel(model_t *mod, qboolean crash)
407 {
408     unsigned *buf;
409     byte stackbuf[1024];	// avoid dirtying the cache heap
410     unsigned long size;
411 
412     if (!mod->needload) {
413 	if (mod->type == mod_alias) {
414 	    if (Cache_Check(&mod->cache))
415 		return mod;
416 	} else
417 	    return mod;		// not cached at all
418     }
419 //
420 // load the file
421 //
422     buf = (unsigned int*)COM_LoadStackFile(mod->name, stackbuf, sizeof(stackbuf), &size);
423     if (!buf) {
424 	if (crash)
425 	    SV_Error("%s: %s not found", __func__, mod->name);
426 	return NULL;
427     }
428 //
429 // allocate a new model
430 //
431     COM_FileBase(mod->name, loadname, sizeof(loadname));
432 
433     loadmodel = mod;
434 
435 //
436 // fill it in
437 //
438 
439 // call the apropriate loader
440     mod->needload = false;
441 
442     switch (LittleLong(*(unsigned *)buf))
443     {
444 #ifndef SERVERONLY
445        case IDPOLYHEADER:
446           Mod_LoadAliasModel(mod_loader, mod, buf, loadmodel, loadname);
447           break;
448 
449        case IDSPRITEHEADER:
450           Mod_LoadSpriteModel(mod, buf, loadname);
451           break;
452 #endif
453        default:
454           Mod_LoadBrushModel(mod, buf, size);
455           break;
456     }
457 
458     return mod;
459 }
460 
461 /*
462 ==================
463 Mod_ForName
464 
465 Loads in a model for the given name
466 ==================
467 */
468 model_t *
Mod_ForName(const char * name,qboolean crash)469 Mod_ForName(const char *name, qboolean crash)
470 {
471     model_t *mod;
472 
473     mod = Mod_FindName(name);
474 
475     return Mod_LoadModel(mod, crash);
476 }
477 
478 
479 /*
480 ===============================================================================
481 
482 					BRUSHMODEL LOADING
483 
484 ===============================================================================
485 */
486 
487 static byte *mod_base;
488 
489 
490 /*
491 =================
492 Mod_LoadTextures
493 =================
494 */
495 static void
Mod_LoadTextures(lump_t * l)496 Mod_LoadTextures(lump_t *l)
497 {
498    int i, j, pixels, num, max, altmax = 0;
499    miptex_t *mt;
500    texture_t *tx, *tx2;
501    texture_t *anims[10];
502    texture_t *altanims[10];
503    dmiptexlump_t *m;
504 
505    if (!l->filelen) {
506       loadmodel->textures = NULL;
507       return;
508    }
509    m = (dmiptexlump_t *)(mod_base + l->fileofs);
510 
511 #ifdef MSB_FIRST
512    m->nummiptex = LittleLong(m->nummiptex);
513 #endif
514 
515    loadmodel->numtextures = m->nummiptex;
516    loadmodel->textures = (texture_t**)Hunk_AllocName(m->nummiptex * sizeof(*loadmodel->textures), loadname);
517 
518    for (i = 0; i < m->nummiptex; i++)
519    {
520 #ifdef MSB_FIRST
521       m->dataofs[i] = LittleLong(m->dataofs[i]);
522 #endif
523       if (m->dataofs[i] == -1)
524          continue;
525       mt = (miptex_t *)((byte *)m + m->dataofs[i]);
526 #ifdef MSB_FIRST
527       mt->width = (uint32_t)LittleLong(mt->width);
528       mt->height = (uint32_t)LittleLong(mt->height);
529       for (j = 0; j < MIPLEVELS; j++)
530          mt->offsets[j] = (uint32_t)LittleLong(mt->offsets[j]);
531 #endif
532 
533       if ((mt->width & 15) || (mt->height & 15))
534          SV_Error("Texture %s is not 16 aligned", mt->name);
535       pixels = mt->width * mt->height / 64 * 85;
536       tx = (texture_t*)Hunk_AllocName(sizeof(texture_t) + pixels, loadname);
537       loadmodel->textures[i] = tx;
538 
539       memcpy(tx->name, mt->name, sizeof(tx->name));
540       tx->width = mt->width;
541       tx->height = mt->height;
542       for (j = 0; j < MIPLEVELS; j++)
543          tx->offsets[j] =
544             mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
545       // the pixels immediately follow the structures
546       memcpy(tx + 1, mt + 1, pixels);
547 
548 #ifndef SERVERONLY
549       if (!strncmp(mt->name, "sky", 3))
550          R_InitSky(tx);
551 #endif
552    }
553 
554    //
555    // sequence the animations
556    //
557    for (i = 0; i < m->nummiptex; i++) {
558       tx = loadmodel->textures[i];
559       if (!tx || tx->name[0] != '+')
560          continue;
561       if (tx->anim_next)
562          continue;		// allready sequenced
563 
564       // find the number of frames in the animation
565       memset(anims, 0, sizeof(anims));
566       memset(altanims, 0, sizeof(altanims));
567 
568       max = tx->name[1];
569       if (max >= 'a' && max <= 'z')
570          max -= 'a' - 'A';
571       if (max >= '0' && max <= '9') {
572          max -= '0';
573          altmax = 0;
574          anims[max] = tx;
575          max++;
576       } else if (max >= 'A' && max <= 'J') {
577          altmax = max - 'A';
578          max = 0;
579          altanims[altmax] = tx;
580          altmax++;
581       } else
582          SV_Error("Bad animating texture %s", tx->name);
583 
584       for (j = i + 1; j < m->nummiptex; j++) {
585          tx2 = loadmodel->textures[j];
586          if (!tx2 || tx2->name[0] != '+')
587             continue;
588          if (strcmp(tx2->name + 2, tx->name + 2))
589             continue;
590 
591          num = tx2->name[1];
592          if (num >= 'a' && num <= 'z')
593             num -= 'a' - 'A';
594          if (num >= '0' && num <= '9') {
595             num -= '0';
596             anims[num] = tx2;
597             if (num + 1 > max)
598                max = num + 1;
599          } else if (num >= 'A' && num <= 'J') {
600             num = num - 'A';
601             altanims[num] = tx2;
602             if (num + 1 > altmax)
603                altmax = num + 1;
604          } else
605             SV_Error("Bad animating texture %s", tx->name);
606       }
607 
608 #define	ANIM_CYCLE	2
609       // link them all together
610       for (j = 0; j < max; j++) {
611          tx2 = anims[j];
612          if (!tx2)
613             SV_Error("Missing frame %i of %s", j, tx->name);
614          tx2->anim_total = max * ANIM_CYCLE;
615          tx2->anim_min = j * ANIM_CYCLE;
616          tx2->anim_max = (j + 1) * ANIM_CYCLE;
617          tx2->anim_next = anims[(j + 1) % max];
618          if (altmax)
619             tx2->alternate_anims = altanims[0];
620       }
621       for (j = 0; j < altmax; j++) {
622          tx2 = altanims[j];
623          if (!tx2)
624             SV_Error("Missing frame %i of %s", j, tx->name);
625          tx2->anim_total = altmax * ANIM_CYCLE;
626          tx2->anim_min = j * ANIM_CYCLE;
627          tx2->anim_max = (j + 1) * ANIM_CYCLE;
628          tx2->anim_next = altanims[(j + 1) % altmax];
629          if (max)
630             tx2->alternate_anims = anims[0];
631       }
632    }
633 }
634 
635 /*
636 =================
637 Mod_LoadLighting
638 =================
639 */
640 
641 
642 static void
Mod_LoadLighting(lump_t * l)643 Mod_LoadLighting(lump_t *l)
644 {
645 	int		i;
646 	byte	*in, *out, *data;
647 	byte	d;
648 	char	litname[1024];
649 	byte 	*lightmapfile;
650 
651 	if (!l->filelen) {
652 		loadmodel->lightdata = NULL;
653 		return;
654 	}
655 
656 	if (coloredlights)	// if colored lights are enabled, look for a lit file to load
657 	{
658 		strcpy(litname, loadmodel->name);
659 		COM_StripExtension(litname);
660 		COM_DefaultExtension(litname, ".lit");
661 		lightmapfile = COM_LoadHunkFile(litname);
662 		if (lightmapfile)
663 		{
664 			data = lightmapfile;
665 			if (data[0] == 'Q' && data[1] == 'L' && data[2] == 'I' && data[3] == 'T')
666 			{
667 				i = LittleLong(((int *)data)[1]);
668 				if (i == 1)
669 				{
670 					loadmodel->lightdata = data + 8;
671 					return;
672 				}
673 				else
674 					Con_Printf("Unknown .LIT file version (%d)\n", i);
675 			}
676 			else
677 				Con_Printf("Corrupt .LIT file (old version?), ignoring\n");
678 
679 		}
680 		else
681 		{
682 		//expand the mono lighting to 24 bit
683 			int i;
684 			byte *dest, *src = mod_base + l->fileofs;
685 			loadmodel->lightdata = Hunk_AllocName ( l->filelen*3, loadname);
686 			dest = loadmodel->lightdata;
687 			for (i = 0; i<l->filelen; i++)
688 			{
689 				dest[0] = *src;
690 				dest[1] = *src;
691 				dest[2] = *src;
692 
693 				src++;
694 				dest+=3;
695 
696 			}
697 
698 
699 		}
700 	}
701 	else		// mono lights
702 	{
703 	    loadmodel->lightdata = (byte*)Hunk_AllocName(l->filelen, loadname);
704 	    memcpy(loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
705 	}
706 }
707 
708 
709 /*
710 =================
711 Mod_LoadVisibility
712 =================
713 */
714 static void
Mod_LoadVisibility(lump_t * l)715 Mod_LoadVisibility(lump_t *l)
716 {
717     if (!l->filelen) {
718 	loadmodel->visdata = NULL;
719 	return;
720     }
721     loadmodel->visdata = (byte*)Hunk_AllocName(l->filelen, loadname);
722     memcpy(loadmodel->visdata, mod_base + l->fileofs, l->filelen);
723 }
724 
725 
726 /*
727 =================
728 Mod_LoadEntities
729 =================
730 */
731 static void
Mod_LoadEntities(lump_t * l)732 Mod_LoadEntities(lump_t *l)
733 {
734     if (!l->filelen) {
735 	loadmodel->entities = NULL;
736 	return;
737     }
738     loadmodel->entities = (char*)Hunk_AllocName(l->filelen, loadname);
739     memcpy(loadmodel->entities, mod_base + l->fileofs, l->filelen);
740 }
741 
742 
743 /*
744 =================
745 Mod_LoadVertexes
746 =================
747 */
748 static void
Mod_LoadVertexes(lump_t * l)749 Mod_LoadVertexes(lump_t *l)
750 {
751    dvertex_t *in;
752    mvertex_t *out;
753    int i, count;
754 
755    in = (dvertex_t*)(void *)(mod_base + l->fileofs);
756    if (l->filelen % sizeof(*in))
757       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
758    count = l->filelen / sizeof(*in);
759    out = (mvertex_t*)Hunk_AllocName(count * sizeof(*out), loadname);
760 
761    loadmodel->vertexes = out;
762    loadmodel->numvertexes = count;
763 
764    for (i = 0; i < count; i++, in++, out++)
765    {
766 #ifdef MSB_FIRST
767       out->position[0] = LittleFloat(in->point[0]);
768       out->position[1] = LittleFloat(in->point[1]);
769       out->position[2] = LittleFloat(in->point[2]);
770 #else
771       out->position[0] = (in->point[0]);
772       out->position[1] = (in->point[1]);
773       out->position[2] = (in->point[2]);
774 #endif
775    }
776 }
777 
778 /*
779 =================
780 Mod_LoadSubmodels
781 =================
782 */
783 static void
Mod_LoadSubmodels(lump_t * l)784 Mod_LoadSubmodels(lump_t *l)
785 {
786    dmodel_t *in;
787    dmodel_t *out;
788    int i, j, count;
789 
790    in = (dmodel_t*)(void *)(mod_base + l->fileofs);
791    if (l->filelen % sizeof(*in))
792       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
793    count = l->filelen / sizeof(*in);
794    out = (dmodel_t*)Hunk_AllocName(count * sizeof(*out), loadname);
795 
796    loadmodel->submodels = out;
797    loadmodel->numsubmodels = count;
798 
799    for (i = 0; i < count; i++, in++, out++)
800    {
801       for (j = 0; j < 3; j++)
802       {	// spread the mins / maxs by a pixel
803 #ifdef MSB_FIRST
804          out->mins[j]   = LittleFloat(in->mins[j]) - 1;
805          out->maxs[j]   = LittleFloat(in->maxs[j]) + 1;
806          out->origin[j] = LittleFloat(in->origin[j]);
807 #else
808          out->mins[j]   = (in->mins[j]) - 1;
809          out->maxs[j]   = (in->maxs[j]) + 1;
810          out->origin[j] = (in->origin[j]);
811 #endif
812       }
813       for (j = 0; j < MAX_MAP_HULLS; j++)
814       {
815 #ifdef MSB_FIRST
816          out->headnode[j] = LittleLong(in->headnode[j]);
817 #else
818          out->headnode[j] = (in->headnode[j]);
819 #endif
820       }
821 #ifdef MSB_FIRST
822       out->visleafs  = LittleLong(in->visleafs);
823       out->firstface = LittleLong(in->firstface);
824       out->numfaces  = LittleLong(in->numfaces);
825 #else
826       out->visleafs  =  (in->visleafs);
827       out->firstface = (in->firstface);
828       out->numfaces  = (in->numfaces);
829 #endif
830    }
831 }
832 
833 /*
834 =================
835 Mod_LoadEdges
836  => Two versions for the different BSP file formats
837 =================
838 */
839 static void
Mod_LoadEdges_BSP29(lump_t * l)840 Mod_LoadEdges_BSP29(lump_t *l)
841 {
842    bsp29_dedge_t *in;
843    medge_t *out;
844    int i, count;
845 
846    in = (bsp29_dedge_t *)(mod_base + l->fileofs);
847    if (l->filelen % sizeof(*in))
848       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
849    count = l->filelen / sizeof(*in);
850    out = (medge_t*)Hunk_AllocName((count + 1) * sizeof(*out), loadname);
851 
852    loadmodel->edges = out;
853    loadmodel->numedges = count;
854 
855    for (i = 0; i < count; i++, in++, out++)
856    {
857 #ifdef MSB_FIRST
858       out->v[0] = (uint16_t)LittleShort(in->v[0]);
859       out->v[1] = (uint16_t)LittleShort(in->v[1]);
860 #else
861       out->v[0] = (uint16_t)(in->v[0]);
862       out->v[1] = (uint16_t)(in->v[1]);
863 #endif
864    }
865 }
866 
867 static void
Mod_LoadEdges_BSP2(lump_t * l)868 Mod_LoadEdges_BSP2(lump_t *l)
869 {
870    bsp2_dedge_t *in;
871    medge_t *out;
872    int i, count;
873 
874    in = (bsp2_dedge_t *)(mod_base + l->fileofs);
875    if (l->filelen % sizeof(*in))
876       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
877    count = l->filelen / sizeof(*in);
878    out = (medge_t*)Hunk_AllocName((count + 1) * sizeof(*out), loadname);
879 
880    loadmodel->edges = out;
881    loadmodel->numedges = count;
882 
883    for (i = 0; i < count; i++, in++, out++) {
884 #ifdef MSB_FIRST
885       out->v[0] = (uint32_t)LittleLong(in->v[0]);
886       out->v[1] = (uint32_t)LittleLong(in->v[1]);
887 #else
888       out->v[0] = (uint32_t)(in->v[0]);
889       out->v[1] = (uint32_t)(in->v[1]);
890 #endif
891    }
892 }
893 
894 /*
895 =================
896 Mod_LoadTexinfo
897 =================
898 */
Mod_LoadTexinfo(lump_t * l)899 static void Mod_LoadTexinfo(lump_t *l)
900 {
901    texinfo_t *in;
902    mtexinfo_t *out;
903    int i, j, count;
904    int miptex;
905    float len1, len2;
906 
907    in = (texinfo_t*)(void *)(mod_base + l->fileofs);
908    if (l->filelen % sizeof(*in))
909       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
910    count = l->filelen / sizeof(*in);
911    out = (mtexinfo_t*)Hunk_AllocName(count * sizeof(*out), loadname);
912 
913    loadmodel->texinfo = out;
914    loadmodel->numtexinfo = count;
915 
916    for (i = 0; i < count; i++, in++, out++)
917    {
918       for (j = 0; j < 4; j++)
919       {
920 #ifdef MSB_FIRST
921          out->vecs[0][j] = LittleFloat(in->vecs[0][j]);
922          out->vecs[1][j] = LittleFloat(in->vecs[1][j]);
923 #else
924          out->vecs[0][j] = (in->vecs[0][j]);
925          out->vecs[1][j] = (in->vecs[1][j]);
926 #endif
927       }
928       len1 = Length(out->vecs[0]);
929       len2 = Length(out->vecs[1]);
930       len1 = (len1 + len2) / 2;
931       if (len1 < 0.32)
932          out->mipadjust = 4;
933       else if (len1 < 0.49)
934          out->mipadjust = 3;
935       else if (len1 < 0.99)
936          out->mipadjust = 2;
937       else
938          out->mipadjust = 1;
939 
940 #ifdef MSB_FIRST
941       miptex     = LittleLong(in->miptex);
942       out->flags = LittleLong(in->flags);
943 #else
944       miptex     = (in->miptex);
945       out->flags = (in->flags);
946 #endif
947 
948       if (!loadmodel->textures) {
949 #ifndef SERVERONLY
950          out->texture = r_notexture_mip;	// checkerboard texture
951 #else
952          out->texture = &r_notexture_mip_qwsv;	// checkerboard texture
953 #endif
954          out->flags = 0;
955       } else {
956          if (miptex >= loadmodel->numtextures)
957             SV_Error("miptex >= loadmodel->numtextures");
958          out->texture = loadmodel->textures[miptex];
959          if (!out->texture) {
960 #ifndef SERVERONLY
961             out->texture = r_notexture_mip;	// texture not found
962 #else
963             out->texture = &r_notexture_mip_qwsv;	// texture not found
964 #endif
965             out->flags = 0;
966          }
967       }
968    }
969 }
970 
971 /*
972 ================
973 CalcSurfaceExtents
974 
975 Fills in s->texturemins[] and s->extents[]
976 ================
977 */
978 static void
CalcSurfaceExtents(msurface_t * s)979 CalcSurfaceExtents(msurface_t *s)
980 {
981     float mins[2], maxs[2], val;
982     int i, j, e;
983     mvertex_t *v;
984     mtexinfo_t *tex;
985     int bmins[2], bmaxs[2];
986 
987     mins[0] = mins[1] = FLT_MAX;
988     maxs[0] = maxs[1] = -FLT_MAX;
989 
990     tex = s->texinfo;
991 
992     for (i = 0; i < s->numedges; i++) {
993 	e = loadmodel->surfedges[s->firstedge + i];
994 	if (e >= 0)
995 	    v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
996 	else
997 	    v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
998 
999 /*
1000 	 * The (long double) casts below are important: The original code was
1001 	 * written for x87 floating-point which uses 80-bit floats for
1002 	 * intermediate calculations. But if you compile it without the casts
1003 	 * for modern x86_64, the compiler will round each intermediate result
1004 	 * to a 32-bit float, which introduces extra rounding error.
1005 	 *
1006 	 * This becomes a problem if the rounding error causes the light
1007 	 * utilities and the engine to disagree about the lightmap size for
1008 	 * some surfaces.
1009 	 *
1010 	 * Casting to (long double) keeps the intermediate values at at least
1011 	 * 64 bits of precision, probably 128.
1012 	 */
1013 
1014 	for (j = 0; j < 2; j++) {
1015        val =
1016 		(long double)v->position[0] * tex->vecs[j][0] +
1017 		(long double)v->position[1] * tex->vecs[j][1] +
1018 		(long double)v->position[2] * tex->vecs[j][2] +
1019 		                                   tex->vecs[j][3];
1020 	    if (val < mins[j])
1021 		mins[j] = val;
1022 	    if (val > maxs[j])
1023 		maxs[j] = val;
1024 	}
1025     }
1026 
1027     for (i = 0; i < 2; i++) {
1028 	bmins[i] = floor(mins[i] / 16);
1029 	bmaxs[i] = ceil(maxs[i] / 16);
1030 
1031 	s->texturemins[i] = bmins[i] * 16;
1032 	s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
1033 	if (!(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
1034 	    SV_Error("Bad surface extents");
1035     }
1036 }
1037 
1038 static void
CalcSurfaceBounds(msurface_t * surf)1039 CalcSurfaceBounds(msurface_t *surf)
1040 {
1041     int i, j, edgenum;
1042     medge_t *edge;
1043     mvertex_t *v;
1044 
1045     surf->mins[0] = surf->mins[1] = surf->mins[2] = FLT_MAX;
1046     surf->maxs[0] = surf->maxs[1] = surf->maxs[2] = -FLT_MAX;
1047 
1048     for (i = 0; i < surf->numedges; i++) {
1049 	edgenum = loadmodel->surfedges[surf->firstedge + i];
1050 	if (edgenum >= 0) {
1051 	    edge = &loadmodel->edges[edgenum];
1052 	    v = &loadmodel->vertexes[edge->v[0]];
1053 	} else {
1054 	    edge = &loadmodel->edges[-edgenum];
1055 	    v = &loadmodel->vertexes[edge->v[1]];
1056 	}
1057 
1058 	for (j = 0; j < 3; j++) {
1059 	    if (surf->mins[j] > v->position[j])
1060 		surf->mins[j] = v->position[j];
1061 	    if (surf->maxs[j] < v->position[j])
1062 		surf->maxs[j] = v->position[j];
1063 	}
1064     }
1065 }
1066 
1067 /*
1068 =================
1069 Mod_LoadFaces
1070  => Two versions for the different BSP file formats
1071 =================
1072 */
1073 static void
Mod_LoadFaces_BSP29(lump_t * l)1074 Mod_LoadFaces_BSP29(lump_t *l)
1075 {
1076    bsp29_dface_t *in;
1077    msurface_t *out;
1078    int i, count, surfnum;
1079    int planenum, side;
1080 
1081    in = (bsp29_dface_t *)(mod_base + l->fileofs);
1082    if (l->filelen % sizeof(*in))
1083       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1084    count = l->filelen / sizeof(*in);
1085    out = (msurface_t*)Hunk_AllocName(count * sizeof(*out), loadname);
1086 
1087    loadmodel->surfaces = out;
1088    loadmodel->numsurfaces = count;
1089 
1090    for (surfnum = 0; surfnum < count; surfnum++, in++, out++)
1091    {
1092 #ifdef MSB_FIRST
1093       out->firstedge = LittleLong(in->firstedge);
1094       out->numedges  = LittleShort(in->numedges);
1095 #else
1096       out->firstedge = (in->firstedge);
1097       out->numedges  = (in->numedges);
1098 #endif
1099       out->flags = 0;
1100 
1101       /* FIXME - Also check numedges doesn't overflow edges */
1102       if (out->numedges <= 0)
1103          SV_Error("%s: bmodel %s has surface with no edges", __func__,
1104                loadmodel->name);
1105 
1106 #ifdef MSB_FIRST
1107       planenum = LittleShort(in->planenum);
1108       side     = LittleShort(in->side);
1109 #else
1110       planenum = (in->planenum);
1111       side     = (in->side);
1112 #endif
1113       if (side)
1114          out->flags |= SURF_PLANEBACK;
1115 
1116       out->plane = loadmodel->planes + planenum;
1117 #ifdef MSB_FIRST
1118       out->texinfo = loadmodel->texinfo + LittleShort(in->texinfo);
1119 #else
1120       out->texinfo = &loadmodel->texinfo[in->texinfo];
1121 #endif
1122 
1123       CalcSurfaceExtents(out);
1124       CalcSurfaceBounds(out);
1125 
1126       // lighting info
1127 
1128       for (i = 0; i < MAXLIGHTMAPS; i++)
1129          out->styles[i] = in->styles[i];
1130 #ifdef MSB_FIRST
1131       i = LittleLong(in->lightofs);
1132 #else
1133       i = (in->lightofs);
1134 #endif
1135       if (coloredlights)
1136       {
1137          if (i == -1)
1138             out->samples = NULL;
1139          out->samples = loadmodel->lightdata + i * 3;
1140       }
1141       else
1142       {
1143          if (i == -1)
1144             out->samples = NULL;
1145          else
1146             out->samples = loadmodel->lightdata + i;
1147       }
1148 
1149       /* set the surface drawing flags */
1150       if (!strncmp(out->texinfo->texture->name, "sky", 3)) {
1151          out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
1152       } else if (!strncmp(out->texinfo->texture->name, "*", 1)) {
1153          out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
1154          for (i = 0; i < 2; i++) {
1155             out->extents[i] = 16384;
1156             out->texturemins[i] = -8192;
1157          }
1158       }
1159    }
1160 }
1161 
Mod_LoadFaces_BSP2(lump_t * l)1162 static void Mod_LoadFaces_BSP2(lump_t *l)
1163 {
1164    msurface_t *out;
1165    int i, count, surfnum;
1166    int planenum, side;
1167    bsp2_dface_t *in = (bsp2_dface_t *)(mod_base + l->fileofs);
1168 
1169    if (l->filelen % sizeof(*in))
1170       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1171 
1172    count = l->filelen / sizeof(*in);
1173    out = (msurface_t*)Hunk_AllocName(count * sizeof(*out), loadname);
1174 
1175    loadmodel->surfaces = out;
1176    loadmodel->numsurfaces = count;
1177 
1178    for (surfnum = 0; surfnum < count; surfnum++, in++, out++)
1179    {
1180 #ifdef MSB_FIRST
1181       out->firstedge = LittleLong(in->firstedge);
1182       out->numedges  = LittleLong(in->numedges);
1183 #else
1184       out->firstedge = (in->firstedge);
1185       out->numedges  = (in->numedges);
1186 #endif
1187       out->flags     = 0;
1188 
1189 #ifdef MSB_FIRST
1190       planenum       = LittleLong(in->planenum);
1191       side           = LittleLong(in->side);
1192 #else
1193       planenum       = (in->planenum);
1194       side           = (in->side);
1195 #endif
1196       if (side)
1197          out->flags |= SURF_PLANEBACK;
1198 
1199       out->plane = loadmodel->planes + planenum;
1200 #ifdef MSB_FIRST
1201       out->texinfo = loadmodel->texinfo + LittleLong(in->texinfo);
1202 #else
1203       out->texinfo = &loadmodel->texinfo[in->texinfo];
1204 #endif
1205 
1206       CalcSurfaceExtents(out);
1207       CalcSurfaceBounds(out);
1208 
1209       // lighting info
1210 
1211       for (i = 0; i < MAXLIGHTMAPS; i++)
1212          out->styles[i] = in->styles[i];
1213 #ifdef MSB_FIRST
1214       i = LittleLong(in->lightofs);
1215 #else
1216       i = (in->lightofs);
1217 #endif
1218       if (i == -1)
1219          out->samples = NULL;
1220       else
1221          out->samples = loadmodel->lightdata + i;
1222 
1223       /* set the surface drawing flags */
1224       if (!strncmp(out->texinfo->texture->name, "sky", 3))
1225          out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
1226       else if (!strncmp(out->texinfo->texture->name, "*", 1))
1227       {
1228          out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
1229          for (i = 0; i < 2; i++)
1230          {
1231             out->extents[i] = 16384;
1232             out->texturemins[i] = -8192;
1233          }
1234       }
1235    }
1236 }
1237 
1238 /*
1239 =================
1240 Mod_SetParent
1241 =================
1242 */
1243 static void
Mod_SetParent(mnode_t * node,mnode_t * parent)1244 Mod_SetParent(mnode_t *node, mnode_t *parent)
1245 {
1246     node->parent = parent;
1247     if (node->contents < 0)
1248 	return;
1249     Mod_SetParent(node->children[0], node);
1250     Mod_SetParent(node->children[1], node);
1251 }
1252 
1253 /*
1254 =================
1255 Mod_LoadNodes
1256  => Two versions for the different BSP file formats
1257 =================
1258 */
1259 static void
Mod_LoadNodes_BSP29(lump_t * l)1260 Mod_LoadNodes_BSP29(lump_t *l)
1261 {
1262    int i, j, count, p;
1263    bsp29_dnode_t *in;
1264    mnode_t *out;
1265 
1266    in = (bsp29_dnode_t *)(mod_base + l->fileofs);
1267    if (l->filelen % sizeof(*in))
1268       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1269    count = l->filelen / sizeof(*in);
1270    out = (mnode_t*)Hunk_AllocName(count * sizeof(*out), loadname);
1271 
1272    loadmodel->nodes = out;
1273    loadmodel->numnodes = count;
1274 
1275    for (i = 0; i < count; i++, in++, out++) {
1276       for (j = 0; j < 3; j++) {
1277 #ifdef MSB_FIRST
1278          out->mins[j] = LittleShort(in->mins[j]);
1279          out->maxs[j] = LittleShort(in->maxs[j]);
1280 #else
1281          out->mins[j] = (in->mins[j]);
1282          out->maxs[j] = (in->maxs[j]);
1283 #endif
1284       }
1285 
1286 #ifdef MSB_FIRST
1287       p = LittleLong(in->planenum);
1288 #else
1289       p = (in->planenum);
1290 #endif
1291       out->plane = loadmodel->planes + p;
1292 
1293 #ifdef MSB_FIRST
1294       out->firstsurface = (uint16_t)LittleShort(in->firstface);
1295       out->numsurfaces = (uint16_t)LittleShort(in->numfaces);
1296 #else
1297       out->firstsurface = (uint16_t)(in->firstface);
1298       out->numsurfaces = (uint16_t)(in->numfaces);
1299 #endif
1300 
1301       for (j = 0; j < 2; j++)
1302       {
1303 #ifdef MSB_FIRST
1304          p = LittleShort(in->children[j]);
1305 #else
1306          p = (in->children[j]);
1307 #endif
1308          if (p >= 0)
1309             out->children[j] = loadmodel->nodes + p;
1310          else
1311             out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
1312       }
1313    }
1314 
1315    Mod_SetParent(loadmodel->nodes, NULL);	// sets nodes and leafs
1316 }
1317 
Mod_LoadNodes_BSP2(lump_t * l)1318 static void Mod_LoadNodes_BSP2(lump_t *l)
1319 {
1320    int i, count;
1321    mnode_t *out;
1322    bsp2_dnode_t *in = (bsp2_dnode_t *)(mod_base + l->fileofs);
1323 
1324    if (l->filelen % sizeof(*in))
1325       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1326 
1327    count = l->filelen / sizeof(*in);
1328    out   = (mnode_t*)Hunk_AllocName(count * sizeof(*out), loadname);
1329 
1330    loadmodel->nodes    = out;
1331    loadmodel->numnodes = count;
1332 
1333    for (i = 0; i < count; i++, in++, out++)
1334    {
1335       int j, p;
1336 
1337       for (j = 0; j < 3; j++)
1338       {
1339 #ifdef MSB_FIRST
1340          out->mins[j] = LittleShort(in->mins[j]);
1341          out->maxs[j] = LittleShort(in->maxs[j]);
1342 #else
1343          out->mins[j] = (in->mins[j]);
1344          out->maxs[j] = (in->maxs[j]);
1345 #endif
1346       }
1347 
1348 #ifdef MSB_FIRST
1349       p = LittleLong(in->planenum);
1350 #else
1351       p = (in->planenum);
1352 #endif
1353       out->plane = loadmodel->planes + p;
1354 
1355 #ifdef MSB_FIRST
1356       out->firstsurface = (uint32_t)LittleLong(in->firstface);
1357       out->numsurfaces = (uint32_t)LittleLong(in->numfaces);
1358 #else
1359       out->firstsurface = (uint32_t)(in->firstface);
1360       out->numsurfaces = (uint32_t)(in->numfaces);
1361 #endif
1362 
1363       for (j = 0; j < 2; j++)
1364       {
1365 #ifdef MSB_FIRST
1366          p = LittleLong(in->children[j]);
1367 #else
1368          p = (in->children[j]);
1369 #endif
1370          if (p >= 0)
1371             out->children[j] = loadmodel->nodes + p;
1372          else
1373             out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
1374       }
1375    }
1376 
1377    Mod_SetParent(loadmodel->nodes, NULL);	// sets nodes and leafs
1378 }
1379 
1380 /*
1381 =================
1382 Mod_LoadLeafs
1383  => Two versions for the different BSP file formats
1384 =================
1385 */
1386 static void
Mod_LoadLeafs_BSP29(lump_t * l)1387 Mod_LoadLeafs_BSP29(lump_t *l)
1388 {
1389    bsp29_dleaf_t *in;
1390    mleaf_t *out;
1391    int i, j, count, p;
1392 
1393    in = (bsp29_dleaf_t *)(mod_base + l->fileofs);
1394    if (l->filelen % sizeof(*in))
1395       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1396    count = l->filelen / sizeof(*in);
1397    out = (mleaf_t*)Hunk_AllocName(count * sizeof(*out), loadname);
1398 
1399    loadmodel->leafs = out;
1400    loadmodel->numleafs = count;
1401 
1402    for (i = 0; i < count; i++, in++, out++)
1403    {
1404       for (j = 0; j < 3; j++)
1405       {
1406 #ifdef MSB_FIRST
1407          out->mins[j] = LittleShort(in->mins[j]);
1408          out->maxs[j] = LittleShort(in->maxs[j]);
1409 #else
1410          out->mins[j] = (in->mins[j]);
1411          out->maxs[j] = (in->maxs[j]);
1412 #endif
1413       }
1414 
1415 #ifdef MSB_FIRST
1416       p = LittleLong(in->contents);
1417 #else
1418       p = (in->contents);
1419 #endif
1420       out->contents = p;
1421 
1422 #ifdef MSB_FIRST
1423       out->firstmarksurface = loadmodel->marksurfaces +
1424          (uint16_t)LittleShort(in->firstmarksurface);
1425       out->nummarksurfaces = (uint16_t)LittleShort(in->nummarksurfaces);
1426 
1427       p = LittleLong(in->visofs);
1428 #else
1429       out->firstmarksurface = &loadmodel->marksurfaces[in->firstmarksurface];
1430       out->nummarksurfaces = (uint16_t)(in->nummarksurfaces);
1431 
1432       p = (in->visofs);
1433 #endif
1434       if (p == -1)
1435          out->compressed_vis = NULL;
1436       else
1437          out->compressed_vis = loadmodel->visdata + p;
1438       out->efrags = NULL;
1439 
1440       for (j = 0; j < 4; j++)
1441          out->ambient_sound_level[j] = in->ambient_level[j];
1442    }
1443 }
1444 
1445 static void
Mod_LoadLeafs_BSP2(lump_t * l)1446 Mod_LoadLeafs_BSP2(lump_t *l)
1447 {
1448    bsp2_dleaf_t *in;
1449    mleaf_t *out;
1450    int i, j, count, p;
1451 
1452    in = (bsp2_dleaf_t *)(mod_base + l->fileofs);
1453    if (l->filelen % sizeof(*in))
1454       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1455    count = l->filelen / sizeof(*in);
1456    out = (mleaf_t*)Hunk_AllocName(count * sizeof(*out), loadname);
1457 
1458    loadmodel->leafs = out;
1459    loadmodel->numleafs = count;
1460 
1461    for (i = 0; i < count; i++, in++, out++) {
1462       for (j = 0; j < 3; j++) {
1463 #ifdef MSB_FIRST
1464          out->mins[j] = LittleShort(in->mins[j]);
1465          out->maxs[j] = LittleShort(in->maxs[j]);
1466 #else
1467          out->mins[j] = (in->mins[j]);
1468          out->maxs[j] = (in->maxs[j]);
1469 #endif
1470       }
1471 
1472 #ifdef MSB_FIRST
1473       p = LittleLong(in->contents);
1474 #else
1475       p = (in->contents);
1476 #endif
1477       out->contents = p;
1478 
1479 #ifdef MSB_FIRST
1480       out->firstmarksurface = loadmodel->marksurfaces +
1481          (uint32_t)LittleLong(in->firstmarksurface);
1482       out->nummarksurfaces = (uint32_t)LittleLong(in->nummarksurfaces);
1483 
1484       p = LittleLong(in->visofs);
1485 #else
1486       out->firstmarksurface = &loadmodel->marksurfaces[in->firstmarksurface];
1487       out->nummarksurfaces = (uint32_t)(in->nummarksurfaces);
1488 
1489       p = (in->visofs);
1490 #endif
1491 
1492       if (p == -1)
1493          out->compressed_vis = NULL;
1494       else
1495          out->compressed_vis = loadmodel->visdata + p;
1496       out->efrags = NULL;
1497 
1498       for (j = 0; j < 4; j++)
1499          out->ambient_sound_level[j] = in->ambient_level[j];
1500    }
1501 }
1502 
1503 /*
1504 =================
1505 Mod_LoadClipnodes
1506  => Two versions for the different BSP file formats
1507 =================
1508 */
1509 static void
Mod_LoadClipnodes_BSP29(lump_t * l)1510 Mod_LoadClipnodes_BSP29(lump_t *l)
1511 {
1512    bsp29_dclipnode_t *in;
1513    mclipnode_t *out;
1514    int i, j, count;
1515    hull_t *hull;
1516 
1517    in = (bsp29_dclipnode_t *)(mod_base + l->fileofs);
1518    if (l->filelen % sizeof(*in))
1519       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1520    count = l->filelen / sizeof(*in);
1521    out = (mclipnode_t*)Hunk_AllocName(count * sizeof(*out), loadname);
1522 
1523    loadmodel->clipnodes = out;
1524    loadmodel->numclipnodes = count;
1525 
1526    hull = &loadmodel->hulls[1];
1527    hull->clipnodes = out;
1528    hull->firstclipnode = 0;
1529    hull->lastclipnode = count - 1;
1530    hull->planes = loadmodel->planes;
1531    hull->clip_mins[0] = -16;
1532    hull->clip_mins[1] = -16;
1533    hull->clip_mins[2] = -24;
1534    hull->clip_maxs[0] = 16;
1535    hull->clip_maxs[1] = 16;
1536    hull->clip_maxs[2] = 32;
1537 
1538    hull = &loadmodel->hulls[2];
1539    hull->clipnodes = out;
1540    hull->firstclipnode = 0;
1541    hull->lastclipnode = count - 1;
1542    hull->planes = loadmodel->planes;
1543    hull->clip_mins[0] = -32;
1544    hull->clip_mins[1] = -32;
1545    hull->clip_mins[2] = -24;
1546    hull->clip_maxs[0] = 32;
1547    hull->clip_maxs[1] = 32;
1548    hull->clip_maxs[2] = 64;
1549 
1550    for (i = 0; i < count; i++, out++, in++)
1551    {
1552 #ifdef MSB_FIRST
1553       out->planenum = LittleLong(in->planenum);
1554 #else
1555       out->planenum = (in->planenum);
1556 #endif
1557       for (j = 0; j < 2; j++) {
1558 #ifdef MSB_FIRST
1559          out->children[j] = (uint16_t)LittleShort(in->children[j]);
1560 #else
1561          out->children[j] = (uint16_t)(in->children[j]);
1562 #endif
1563          if (out->children[j] > 0xfff0)
1564             out->children[j] -= 0x10000;
1565          if (out->children[j] >= count)
1566             SV_Error("%s: bad clipnode child number", __func__);
1567       }
1568    }
1569 }
1570 
1571 static void
Mod_LoadClipnodes_BSP2(lump_t * l)1572 Mod_LoadClipnodes_BSP2(lump_t *l)
1573 {
1574    bsp2_dclipnode_t *in;
1575    mclipnode_t *out;
1576    int i, j, count;
1577    hull_t *hull;
1578 
1579    in = (bsp2_dclipnode_t *)(mod_base + l->fileofs);
1580    if (l->filelen % sizeof(*in))
1581       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1582    count = l->filelen / sizeof(*in);
1583    out = (mclipnode_t*)Hunk_AllocName(count * sizeof(*out), loadname);
1584 
1585    loadmodel->clipnodes = out;
1586    loadmodel->numclipnodes = count;
1587 
1588    hull = &loadmodel->hulls[1];
1589    hull->clipnodes = out;
1590    hull->firstclipnode = 0;
1591    hull->lastclipnode = count - 1;
1592    hull->planes = loadmodel->planes;
1593    hull->clip_mins[0] = -16;
1594    hull->clip_mins[1] = -16;
1595    hull->clip_mins[2] = -24;
1596    hull->clip_maxs[0] = 16;
1597    hull->clip_maxs[1] = 16;
1598    hull->clip_maxs[2] = 32;
1599 
1600    hull = &loadmodel->hulls[2];
1601    hull->clipnodes = out;
1602    hull->firstclipnode = 0;
1603    hull->lastclipnode = count - 1;
1604    hull->planes = loadmodel->planes;
1605    hull->clip_mins[0] = -32;
1606    hull->clip_mins[1] = -32;
1607    hull->clip_mins[2] = -24;
1608    hull->clip_maxs[0] = 32;
1609    hull->clip_maxs[1] = 32;
1610    hull->clip_maxs[2] = 64;
1611 
1612    for (i = 0; i < count; i++, out++, in++) {
1613 #ifdef MSB_FIRST
1614       out->planenum = LittleLong(in->planenum);
1615 #else
1616       out->planenum = (in->planenum);
1617 #endif
1618       for (j = 0; j < 2; j++) {
1619 #ifdef MSB_FIRST
1620          out->children[j] = LittleLong(in->children[j]);
1621 #else
1622          out->children[j] = (in->children[j]);
1623 #endif
1624          if (out->children[j] >= count)
1625             SV_Error("%s: bad clipnode child number", __func__);
1626       }
1627    }
1628 }
1629 
1630 /*
1631 =================
1632 Mod_MakeHull0
1633 
1634 Duplicate the drawing hull structure as a clipping hull
1635 =================
1636 */
1637 static void
Mod_MakeHull0(void)1638 Mod_MakeHull0(void)
1639 {
1640     mnode_t *in, *child;
1641     mclipnode_t *out;
1642     int i, j, count;
1643     hull_t *hull;
1644 
1645     hull = &loadmodel->hulls[0];
1646 
1647     in = loadmodel->nodes;
1648     count = loadmodel->numnodes;
1649     out = (mclipnode_t*)Hunk_AllocName(count * sizeof(*out), loadname);
1650 
1651     hull->clipnodes = out;
1652     hull->firstclipnode = 0;
1653     hull->lastclipnode = count - 1;
1654     hull->planes = loadmodel->planes;
1655 
1656     for (i = 0; i < count; i++, out++, in++) {
1657 	out->planenum = in->plane - loadmodel->planes;
1658 	for (j = 0; j < 2; j++) {
1659 	    child = in->children[j];
1660 	    if (child->contents < 0)
1661 		out->children[j] = child->contents;
1662 	    else
1663 		out->children[j] = child - loadmodel->nodes;
1664 	}
1665     }
1666 }
1667 
1668 /*
1669 =================
1670 Mod_LoadMarksurfaces
1671  => Two versions for the different BSP file formats
1672 =================
1673 */
1674 static void
Mod_LoadMarksurfaces_BSP29(lump_t * l)1675 Mod_LoadMarksurfaces_BSP29(lump_t *l)
1676 {
1677    int i, j, count;
1678    uint16_t *in;
1679    msurface_t **out;
1680 
1681    in = (uint16_t *)(mod_base + l->fileofs);
1682    if (l->filelen % sizeof(*in))
1683       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1684    count = l->filelen / sizeof(*in);
1685    out = (msurface_t**)Hunk_AllocName(count * sizeof(*out), loadname);
1686 
1687    loadmodel->marksurfaces = out;
1688    loadmodel->nummarksurfaces = count;
1689 
1690    for (i = 0; i < count; i++)
1691    {
1692 #ifdef MSB_FIRST
1693       j = (uint16_t)LittleShort(in[i]);
1694 #else
1695       j = (uint16_t)(in[i]);
1696 #endif
1697       if (j >= loadmodel->numsurfaces)
1698          SV_Error("%s: bad surface number", __func__);
1699       out[i] = loadmodel->surfaces + j;
1700    }
1701 }
1702 
1703 static void
Mod_LoadMarksurfaces_BSP2(lump_t * l)1704 Mod_LoadMarksurfaces_BSP2(lump_t *l)
1705 {
1706    int i, j, count;
1707    uint32_t *in;
1708    msurface_t **out;
1709 
1710    in = (uint32_t *)(mod_base + l->fileofs);
1711    if (l->filelen % sizeof(*in))
1712       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1713    count = l->filelen / sizeof(*in);
1714    out = (msurface_t**)Hunk_AllocName(count * sizeof(*out), loadname);
1715 
1716    loadmodel->marksurfaces = out;
1717    loadmodel->nummarksurfaces = count;
1718 
1719    for (i = 0; i < count; i++) {
1720 #ifdef MSB_FIRST
1721       j = (uint32_t)LittleLong(in[i]);
1722 #else
1723       j = (uint32_t)(in[i]);
1724 #endif
1725       if (j >= loadmodel->numsurfaces)
1726          SV_Error("%s: bad surface number", __func__);
1727       out[i] = loadmodel->surfaces + j;
1728    }
1729 }
1730 
1731 /*
1732 =================
1733 Mod_LoadSurfedges
1734 =================
1735 */
1736 static void
Mod_LoadSurfedges(lump_t * l)1737 Mod_LoadSurfedges(lump_t *l)
1738 {
1739    int i, count;
1740    int *in, *out;
1741 
1742    in = (int*)(void *)(mod_base + l->fileofs);
1743    if (l->filelen % sizeof(*in))
1744       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1745    count = l->filelen / sizeof(*in);
1746    out = (int*)Hunk_AllocName(count * sizeof(*out), loadname);
1747 
1748    loadmodel->surfedges = out;
1749    loadmodel->numsurfedges = count;
1750 
1751    for (i = 0; i < count; i++)
1752 #ifdef MSB_FIRST
1753       out[i] = LittleLong(in[i]);
1754 #else
1755       out[i] = (in[i]);
1756 #endif
1757 }
1758 
1759 /*
1760 =================
1761 Mod_LoadPlanes
1762 =================
1763 */
Mod_LoadPlanes(lump_t * l)1764 static void Mod_LoadPlanes(lump_t *l)
1765 {
1766    int i, j, count;
1767    mplane_t *out;
1768    dplane_t *in = (dplane_t*)(void *)(mod_base + l->fileofs);
1769 
1770    if (l->filelen % sizeof(*in))
1771       SV_Error("%s: funny lump size in %s", __func__, loadmodel->name);
1772 
1773    count = l->filelen / sizeof(*in);
1774    out   = (mplane_t*)
1775       Hunk_AllocName(count * 2 * sizeof(*out), loadname);
1776 
1777    loadmodel->planes    = out;
1778    loadmodel->numplanes = count;
1779 
1780    for (i = 0; i < count; i++, in++, out++)
1781    {
1782       int bits = 0;
1783       for (j = 0; j < 3; j++)
1784       {
1785 #ifdef MSB_FIRST
1786          out->normal[j] = LittleFloat(in->normal[j]);
1787 #else
1788          out->normal[j] = (in->normal[j]);
1789 #endif
1790          if (out->normal[j] < 0)
1791             bits |= 1 << j;
1792       }
1793 
1794 #ifdef MSB_FIRST
1795       out->dist = LittleFloat(in->dist);
1796       out->type = LittleLong(in->type);
1797 #else
1798       out->dist = (in->dist);
1799       out->type = (in->type);
1800 #endif
1801       out->signbits = bits;
1802    }
1803 }
1804 
1805 /*
1806 =================
1807 RadiusFromBounds
1808 =================
1809 */
RadiusFromBounds(vec3_t mins,vec3_t maxs)1810 static float RadiusFromBounds(vec3_t mins, vec3_t maxs)
1811 {
1812    int i;
1813    vec3_t corner;
1814 
1815    for (i = 0; i < 3; i++)
1816       corner[i] = qmax(fabs(mins[i]), fabs(maxs[i]));
1817 
1818    return Length(corner);
1819 }
1820 
1821 /*
1822 =================
1823 Mod_LoadBrushModel
1824 =================
1825 */
Mod_LoadBrushModel(model_t * mod,void * buffer,unsigned long size)1826 static void Mod_LoadBrushModel(model_t *mod, void *buffer, unsigned long size)
1827 {
1828    int i, j;
1829    dheader_t *header;
1830    dmodel_t *bm;
1831 
1832    loadmodel->type = mod_brush;
1833    header = (dheader_t *)buffer;
1834 
1835 #ifdef MSB_FIRST
1836    /* swap all the header entries */
1837    header->version = LittleLong(header->version);
1838    for (i = 0; i < HEADER_LUMPS; i++) {
1839       header->lumps[i].fileofs = LittleLong(header->lumps[i].fileofs);
1840       header->lumps[i].filelen = LittleLong(header->lumps[i].filelen);
1841    }
1842 #endif
1843 
1844    if (header->version != BSPVERSION && header->version != BSP2VERSION)
1845       SV_Error("%s: %s has wrong version number (%i should be %i or %i)",
1846             __func__, mod->name, header->version, BSPVERSION, BSP2VERSION);
1847 
1848    mod_base = (byte *)header;
1849 
1850    /*
1851     * Check the lump extents
1852     * FIXME - do this more generally... cleanly...?
1853     */
1854    for (i = 0; i < HEADER_LUMPS; ++i)
1855    {
1856       int b1 = header->lumps[i].fileofs;
1857       int e1 = b1 + header->lumps[i].filelen;
1858 
1859       /*
1860        * Sanity checks
1861        * - begin and end >= 0 (end might overflow).
1862        * - end > begin (again, overflow reqd.)
1863        * - end < size of file.
1864        */
1865       if (b1 > e1 || e1 > size || b1 < 0 || e1 < 0)
1866          SV_Error("%s: bad lump extents in %s", __func__,
1867                loadmodel->name);
1868 
1869       /* Now, check that it doesn't overlap any other lumps */
1870       for (j = 0; j < HEADER_LUMPS; ++j)
1871       {
1872          int b2 = header->lumps[j].fileofs;
1873          int e2 = b2 + header->lumps[j].filelen;
1874 
1875          if ((b1 < b2 && e1 > b2) || (b2 < b1 && e2 > b1))
1876             SV_Error("%s: overlapping lumps in %s", __func__,
1877                   loadmodel->name);
1878       }
1879    }
1880 
1881 #ifdef QW_HACK
1882    mod->checksum = 0;
1883    mod->checksum2 = 0;
1884 
1885    // checksum all of the map, except for entities
1886    for (i = 0; i < HEADER_LUMPS; i++) {
1887       const lump_t *l = &header->lumps[i];
1888       unsigned int checksum;
1889 
1890       if (i == LUMP_ENTITIES)
1891          continue;
1892       checksum = Com_BlockChecksum(mod_base + l->fileofs, l->filelen);
1893       mod->checksum ^= checksum;
1894       if (i == LUMP_VISIBILITY || i == LUMP_LEAFS || i == LUMP_NODES)
1895          continue;
1896       mod->checksum2 ^= checksum;
1897    }
1898 #ifdef MSB_FIRST
1899    mod->checksum  = LittleLong(mod->checksum);
1900    mod->checksum2 = LittleLong(mod->checksum2);
1901 #endif
1902 #endif
1903 
1904    /* load into heap */
1905    Mod_LoadVertexes(&header->lumps[LUMP_VERTEXES]);
1906    if (header->version == BSPVERSION)
1907       Mod_LoadEdges_BSP29(&header->lumps[LUMP_EDGES]);
1908    else
1909       Mod_LoadEdges_BSP2(&header->lumps[LUMP_EDGES]);
1910    Mod_LoadSurfedges(&header->lumps[LUMP_SURFEDGES]);
1911    Mod_LoadTextures(&header->lumps[LUMP_TEXTURES]);
1912    Mod_LoadLighting(&header->lumps[LUMP_LIGHTING]);
1913    Mod_LoadPlanes(&header->lumps[LUMP_PLANES]);
1914    Mod_LoadTexinfo(&header->lumps[LUMP_TEXINFO]);
1915    if (header->version == BSPVERSION) {
1916       Mod_LoadFaces_BSP29(&header->lumps[LUMP_FACES]);
1917       Mod_LoadMarksurfaces_BSP29(&header->lumps[LUMP_MARKSURFACES]);
1918    } else {
1919       Mod_LoadFaces_BSP2(&header->lumps[LUMP_FACES]);
1920       Mod_LoadMarksurfaces_BSP2(&header->lumps[LUMP_MARKSURFACES]);
1921    }
1922    Mod_LoadVisibility(&header->lumps[LUMP_VISIBILITY]);
1923    if (header->version == BSPVERSION) {
1924       Mod_LoadLeafs_BSP29(&header->lumps[LUMP_LEAFS]);
1925       Mod_LoadNodes_BSP29(&header->lumps[LUMP_NODES]);
1926       Mod_LoadClipnodes_BSP29(&header->lumps[LUMP_CLIPNODES]);
1927    } else {
1928       Mod_LoadLeafs_BSP2(&header->lumps[LUMP_LEAFS]);
1929       Mod_LoadNodes_BSP2(&header->lumps[LUMP_NODES]);
1930       Mod_LoadClipnodes_BSP2(&header->lumps[LUMP_CLIPNODES]);
1931    }
1932    Mod_LoadEntities(&header->lumps[LUMP_ENTITIES]);
1933    Mod_LoadSubmodels(&header->lumps[LUMP_MODELS]);
1934 
1935    Mod_MakeHull0();
1936 
1937    mod->numframes = 2;		// regular and alternate animation
1938    mod->flags = 0;
1939 
1940    /*
1941     * Create space for the decompressed vis data
1942     * - We assume the main map is the first BSP file loaded (should be)
1943     * - If any other model has more leafs, then we may be in trouble...
1944     */
1945          if (mod->numleafs > pvscache_numleafs) {
1946             if (pvscache[0].leafbits)
1947                SV_Error("%s: %d allocated for visdata, but model %s has %d leafs",
1948                      __func__, pvscache_numleafs, loadmodel->name, mod->numleafs);
1949             Mod_InitPVSCache(mod->numleafs);
1950          }
1951 
1952          //
1953          // set up the submodels (FIXME: this is confusing)
1954          //
1955          for (i = 0; i < mod->numsubmodels; i++) {
1956             bm = &mod->submodels[i];
1957 
1958             mod->hulls[0].firstclipnode = bm->headnode[0];
1959             for (j = 1; j < MAX_MAP_HULLS; j++) {
1960                mod->hulls[j].firstclipnode = bm->headnode[j];
1961                mod->hulls[j].lastclipnode = mod->numclipnodes - 1;
1962             }
1963 
1964             mod->firstmodelsurface = bm->firstface;
1965             mod->nummodelsurfaces = bm->numfaces;
1966 
1967             VectorCopy(bm->maxs, mod->maxs);
1968             VectorCopy(bm->mins, mod->mins);
1969 
1970             mod->radius = RadiusFromBounds(mod->mins, mod->maxs);
1971             mod->numleafs = bm->visleafs;
1972 
1973             /* duplicate the basic information */
1974             if (i < mod->numsubmodels - 1) {
1975                char name[10];
1976 
1977                snprintf(name, sizeof(name), "*%i", i + 1);
1978                loadmodel = Mod_FindName(name);
1979                *loadmodel = *mod;
1980                strcpy(loadmodel->name, name);
1981                mod = loadmodel;
1982             }
1983          }
1984 }
1985 
1986 /*
1987  * =========================================================================
1988  *                          CLIENT ONLY FUNCTIONS
1989  * =========================================================================
1990  */
1991 #ifndef SERVERONLY
1992 
1993 /*
1994 ===============
1995 Mod_Extradata
1996 
1997 Caches the data if needed
1998 ===============
1999 */
Mod_Extradata(model_t * mod)2000 void *Mod_Extradata(model_t *mod)
2001 {
2002    void *r = Cache_Check(&mod->cache);
2003    if (r)
2004       return r;
2005 
2006    Mod_LoadModel(mod, true);
2007 
2008    if (!mod->cache.data)
2009       Sys_Error("%s: caching failed", __func__);
2010    return mod->cache.data;
2011 }
2012 
2013 /*
2014 ================
2015 Mod_Print
2016 ================
2017 */
Mod_Print(void)2018 void Mod_Print(void)
2019 {
2020    int i;
2021    model_t *mod;
2022 
2023    Con_Printf("Cached models:\n");
2024    for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
2025       Con_Printf("%*p : %s\n", (int)sizeof(void *) * 2 + 2,
2026             mod->cache.data, mod->name);
2027 }
2028 
2029 /*
2030 ==================
2031 Mod_TouchModel
2032 
2033 ==================
2034 */
Mod_TouchModel(char * name)2035 void Mod_TouchModel(char *name)
2036 {
2037    model_t *mod = Mod_FindName(name);
2038 
2039    if (!mod->needload)
2040    {
2041       if (mod->type == mod_alias)
2042          Cache_Check(&mod->cache);
2043    }
2044 }
2045 
2046 #endif /* !SERVERONLY */
2047