1 /*
2 Copyright (C) 1997-2001 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 //
21 // cm_q3_main.c
22 // Quake3 BSP map model loading
23 // FIXME TODO:
24 // - A lot of these allocations can be better sized (entity string for example).
25 //
26 
27 #include "cm_q3_local.h"
28 
29 static byte				*cm_q3_mapBuffer;
30 
31 static int				cm_q3_numEntityChars;
32 static char				cm_q3_emptyEntityString[1];
33 static char				*cm_q3_entityString = cm_q3_emptyEntityString;
34 
35 int						cm_q3_numBrushSides;
36 cbrushside_t			*cm_q3_brushSides;
37 
38 int						cm_q3_numShaderRefs;
39 cBspSurface_t			*cm_q3_surfaces;
40 
41 int						cm_q3_numPlanes;
42 cBspPlane_t				*cm_q3_planes;
43 
44 int						cm_q3_numNodes;
45 cnode_t					*cm_q3_nodes;
46 
47 int						cm_q3_numLeafs = 1;	// allow leaf funcs to be called without a map
48 cleaf_t					*cm_q3_leafs;
49 
50 int						cm_q3_numLeafBrushes;
51 int						*cm_q3_leafBrushes;
52 
53 int						cm_q3_numBrushes;
54 cbrush_t				*cm_q3_brushes;
55 
56 static int				cm_q3_numVisibility;
57 dQ3BspVis_t				*cm_q3_visData;
58 dQ3BspVis_t				*cm_q3_hearData;
59 
60 byte					*cm_q3_nullRow;
61 
62 // each area has a list of portals that lead into other areas
63 // when portals are closed, other areas may not be visible or
64 // hearable even if the vis info says that it should be
65 int						cm_q3_numAreaPortals = 1;
66 careaportal_t			*cm_q3_areaPortals;
67 
68 int						cm_q3_numAreas = 1;
69 carea_t					*cm_q3_areas;
70 
71 cBspSurface_t			cm_q3_nullSurface;
72 
73 int						cm_q3_emptyLeaf;
74 
75 int						cm_q3_numPatches;
76 cpatch_t				*cm_q3_patches;
77 
78 int						cm_q3_numLeafPatches;
79 int						*cm_q3_leafPatches;
80 
81 // These are only used during load
82 static int				cm_q3_numVertexes;
83 static vec4_t			*cm_q3_mapVerts;
84 
85 static int				cm_q3_numFaces;
86 static cface_t			*cm_q3_mapFaces;
87 
88 static int				cm_q3_numLeafFaces;
89 static int				*cm_q3_leafFaces;
90 
91 /*
92 =============================================================================
93 
94 	PATCH LOADING
95 
96 =============================================================================
97 */
98 
99 /*
100 ===============
101 Patch_FlatnessTest2
102 ===============
103 */
Patch_FlatnessTest2(float maxflat,vec4_t point0,vec4_t point1,vec4_t point2)104 static int Patch_FlatnessTest2 (float maxflat, vec4_t point0, vec4_t point1, vec4_t point2)
105 {
106 	vec3_t	v1, v2, v3;
107 	vec3_t	t, n;
108 	float	dist, d, l;
109 	int		ft0, ft1;
110 
111 	Vec3Subtract (point2, point0, n);
112 	l = VectorNormalizef (n, n);
113 
114 	if (!l)
115 		return 0;
116 
117 	Vec3Subtract (point1, point0, t);
118 	d = -DotProduct (t, n);
119 	Vec3MA (t, d, n, t);
120 	dist = Vec3Length (t);
121 
122 	if (fabs(dist) <= maxflat)
123 		return 0;
124 
125 	Vec3Average (point1, point0, v1);
126 	Vec3Average (point2, point1, v2);
127 	Vec3Average (v1, v2, v3);
128 
129 	ft0 = Patch_FlatnessTest2 (maxflat, point0, v1, v3);
130 	ft1 = Patch_FlatnessTest2 (maxflat, v3, v2, point2);
131 
132 	return 1 + (int)floor(max (ft0, ft1) + 0.5f);
133 }
134 
135 
136 /*
137 ===============
138 Patch_GetFlatness2
139 ===============
140 */
Patch_GetFlatness2(float maxflat,vec4_t * points,int * patch_cp,int * flat)141 static void Patch_GetFlatness2 (float maxflat, vec4_t *points, int *patch_cp, int *flat)
142 {
143 	int	i, p, u, v;
144 
145 	flat[0] = flat[1] = 0;
146 	for (v=0 ; v<patch_cp[1]-1 ; v+=2) {
147 		for (u=0 ; u<patch_cp[0]-1 ; u+=2) {
148 			p = v * patch_cp[0] + u;
149 
150 			i = Patch_FlatnessTest2 (maxflat, points[p], points[p+1], points[p+2]);
151 			flat[0] = max (flat[0], i);
152 			i = Patch_FlatnessTest2 (maxflat, points[p+patch_cp[0]], points[p+patch_cp[0]+1], points[p+patch_cp[0]+2]);
153 			flat[0] = max (flat[0], i);
154 			i = Patch_FlatnessTest2 (maxflat, points[p+2*patch_cp[0]], points[p+2*patch_cp[0]+1], points[p+2*patch_cp[0]+2]);
155 			flat[0] = max (flat[0], i);
156 
157 			i = Patch_FlatnessTest2 (maxflat, points[p], points[p+patch_cp[0]], points[p+2*patch_cp[0]]);
158 			flat[1] = max (flat[1], i);
159 			i = Patch_FlatnessTest2 (maxflat, points[p+1], points[p+patch_cp[0]+1], points[p+2*patch_cp[0]+1]);
160 			flat[1] = max (flat[1], i);
161 			i = Patch_FlatnessTest2 (maxflat, points[p+2], points[p+patch_cp[0]+2], points[p+2*patch_cp[0]+2]);
162 			flat[1] = max (flat[1], i);
163 		}
164 	}
165 }
166 
167 
168 /*
169 ===============
170 Patch_Evaluate_QuadricBezier2
171 ===============
172 */
Patch_Evaluate_QuadricBezier2(float t,vec4_t point0,vec4_t point1,vec3_t point2,vec4_t out)173 static void Patch_Evaluate_QuadricBezier2 (float t, vec4_t point0, vec4_t point1, vec3_t point2, vec4_t out)
174 {
175 	float	qt = t * t;
176 	float	dt = 2.0f * t, tt;
177 	vec4_t	tvec4;
178 
179 	tt = 1.0f - dt + qt;
180 	Vec4Scale (point0, tt, out);
181 
182 	tt = dt - 2.0f * qt;
183 	Vec4Scale (point1, tt, tvec4);
184 	Vec4Add (out, tvec4, out);
185 
186 	Vec4Scale (point2, qt, tvec4);
187 	Vec4Add (out, tvec4, out);
188 }
189 
190 
191 /*
192 ===============
193 Patch_Evaluate2
194 ===============
195 */
Patch_Evaluate2(vec4_t * p,int * numcp,int * tess,vec4_t * dest)196 static void Patch_Evaluate2 (vec4_t *p, int *numcp, int *tess, vec4_t *dest)
197 {
198 	int		num_patches[2], num_tess[2];
199 	int		index[3], dstpitch, i, u, v, x, y;
200 	float	s, t, step[2];
201 	vec4_t	*tvec, pv[3][3], v1, v2, v3;
202 
203 	num_patches[0] = numcp[0] / 2;
204 	num_patches[1] = numcp[1] / 2;
205 	dstpitch = num_patches[0] * tess[0] + 1;
206 
207 	step[0] = 1.0f / (float)tess[0];
208 	step[1] = 1.0f / (float)tess[1];
209 
210 	for (v=0 ; v<num_patches[1] ; v++) {
211 		// Last patch has one more row
212 		if (v < num_patches[1]-1) {
213 			num_tess[1] = tess[1];
214 		}
215 		else {
216 			num_tess[1] = tess[1] + 1;
217 		}
218 
219 		for (u=0 ; u<num_patches[0] ; u++) {
220 			// Last patch has one more column
221 			if (u < num_patches[0] - 1) {
222 				num_tess[0] = tess[0];
223 			}
224 			else {
225 				num_tess[0] = tess[0] + 1;
226 			}
227 
228 			index[0] = (v * numcp[0] + u) * 2;
229 			index[1] = index[0] + numcp[0];
230 			index[2] = index[1] + numcp[0];
231 
232 			// Current 3x3 patch control points
233 			for (i=0 ; i<3 ; i++) {
234 				Vec4Copy (p[index[0]+i], pv[i][0]);
235 				Vec4Copy (p[index[1]+i], pv[i][1]);
236 				Vec4Copy (p[index[2]+i], pv[i][2]);
237 			}
238 
239 			t = 0.0f;
240 			tvec = dest + v * tess[1] * dstpitch + u * tess[0];
241 
242 			for (y=0 ; y<num_tess[1] ; y++, t+=step[1]) {
243 				Patch_Evaluate_QuadricBezier2 (t, pv[0][0], pv[0][1], pv[0][2], v1);
244 				Patch_Evaluate_QuadricBezier2 (t, pv[1][0], pv[1][1], pv[1][2], v2);
245 				Patch_Evaluate_QuadricBezier2 (t, pv[2][0], pv[2][1], pv[2][2], v3);
246 
247 				s = 0.0f;
248 				for (x=0 ; x<num_tess[0] ; x++, s+=step[0])
249 					Patch_Evaluate_QuadricBezier2 (s, v1, v2, v3, tvec[x]);
250 
251 				tvec += dstpitch;
252 			}
253 		}
254 	}
255 }
256 
257 
258 /*
259 ===============
260 CM_Q3BSP_CreateBrush
261 ===============
262 */
CM_Q3BSP_CreateBrush(cbrush_t * brush,vec3_t * verts,cBspSurface_t * surface)263 static void CM_Q3BSP_CreateBrush (cbrush_t *brush, vec3_t *verts, cBspSurface_t *surface)
264 {
265 	static cBspPlane_t mainplane, patchplanes[20];
266 	int				i, j, k, sign;
267 	vec3_t			v1, v2;
268 	vec3_t			absMins, absMaxs;
269 	cbrushside_t	*side;
270 	cBspPlane_t		*plane;
271 	qBool			skip[20];
272 	int				numPatchPlanes = 0;
273 	vec3_t			normal;
274 
275 	// Calc absMins & absMaxs
276 	ClearBounds (absMins, absMaxs);
277 	for (i=0 ; i<3 ; i++)
278 		AddPointToBounds (verts[i], absMins, absMaxs);
279 
280 	PlaneFromPoints (verts, &mainplane);
281 
282 	// Front plane
283 	plane = &patchplanes[numPatchPlanes++];
284 	*plane = mainplane;
285 
286 	// Back plane
287 	plane = &patchplanes[numPatchPlanes++];
288 	Vec3Negate (mainplane.normal, plane->normal);
289 	plane->dist = -mainplane.dist;
290 
291 	// Axial planes
292 	for (i=0 ; i<3 ; i++) {
293 		for (sign=-1 ; sign<=1 ; sign+=2) {
294 			plane = &patchplanes[numPatchPlanes++];
295 			Vec3Clear (plane->normal);
296 			plane->normal[i] = sign;
297 			if (sign > 0)
298 				plane->dist = absMaxs[i];
299 			else
300 				plane->dist = -absMins[i];
301 		}
302 	}
303 
304 	// Edge planes
305 	for (i=0 ; i<3 ; i++) {
306 		Vec3Copy (verts[i], v1);
307 		Vec3Copy (verts[(i + 1) % 3], v2);
308 
309 		for (k=0 ; k<3 ; k++) {
310 			normal[k] = 0;
311 			normal[(k+1)%3] = v1[(k+2)%3] - v2[(k+2)%3];
312 			normal[(k+2)%3] = -(v1[(k+1)%3] - v2[(k+1)%3]);
313 
314 			if (Vec3Compare (normal, vec3Origin))
315 				continue;
316 
317 			plane = &patchplanes[numPatchPlanes++];
318 
319 			VectorNormalizef ( normal, normal );
320 			Vec3Copy ( normal, plane->normal );
321 			plane->dist = DotProduct (plane->normal, v1);
322 
323 			if (DotProduct(verts[(i+2)%3], normal) - plane->dist > 0) {
324 				// Invert
325 				Vec3Inverse (plane->normal);
326 				plane->dist = -plane->dist;
327 			}
328 		}
329 	}
330 
331 	// Set plane->type and mark duplicate planes for removal
332 	for (i=0 ; i<numPatchPlanes ; i++) {
333 		CategorizePlane (&patchplanes[i]);
334 		skip[i] = qFalse;
335 
336 		for (j=i+1 ; j<numPatchPlanes ; j++) {
337 			if (patchplanes[j].dist == patchplanes[i].dist
338 			&& Vec3Compare (patchplanes[j].normal, patchplanes[i].normal)) {
339 				skip[i] = qTrue;
340 				break;
341 			}
342 		}
343 	}
344 
345 	brush->numSides = 0;
346 	brush->firstBrushSide = cm_q3_numBrushSides;
347 
348 	for (k=0 ; k<2 ; k++) {
349 		for (i=0 ; i<numPatchPlanes ; i++) {
350 			if (skip[i])
351 				continue;
352 
353 			// first, store all axially aligned planes
354 			// then store everything else
355 			// does it give a noticeable speedup?
356 			if (!k && patchplanes[i].type >= 3)
357 				continue;
358 
359 			skip[i] = qTrue;
360 
361 			if (cm_q3_numPlanes == MAX_Q3BSP_CM_PLANES)
362 				Com_Error (ERR_DROP, "CM_Q3BSP_CreateBrush: cm_q3_numPlanes == MAX_Q3BSP_CM_PLANES");
363 
364 			plane = &cm_q3_planes[cm_q3_numPlanes++];
365 			*plane = patchplanes[i];
366 
367 			if (cm_q3_numBrushSides == MAX_Q3BSP_CM_BRUSHSIDES)
368 				Com_Error (ERR_DROP, "CM_Q3BSP_CreateBrush: cm_q3_numBrushSides == MAX_Q3BSP_CM_BRUSHSIDES");
369 
370 			side = &cm_q3_brushSides[cm_q3_numBrushSides++];
371 			side->plane = plane;
372 
373 			if (DotProduct(plane->normal, mainplane.normal) >= 0)
374 				side->surface = surface;
375 			else
376 				side->surface = NULL;	// don't clip against this side
377 
378 			brush->numSides++;
379 		}
380 	}
381 }
382 
383 
384 /*
385 ===============
386 CM_Q3BSP_CreatePatch
387 ===============
388 */
CM_Q3BSP_CreatePatch(cpatch_t * patch,int numverts,vec4_t * verts,int * patch_cp)389 static void CM_Q3BSP_CreatePatch (cpatch_t *patch, int numverts, vec4_t *verts, int *patch_cp)
390 {
391     int			step[2], size[2], flat[2], i, u, v;
392 	vec4_t		points[MAX_Q3BSP_CM_PATCH_VERTS];
393 	vec3_t		tverts[4], tverts2[4];
394 	cbrush_t	*brush;
395 	cBspPlane_t	mainplane;
396 
397 	// Find the degree of subdivision in the u and v directions
398 	Patch_GetFlatness2 (CM_SUBDIVLEVEL, verts, patch_cp, flat);
399 
400 	step[0] = (1 << flat[0]);
401 	step[1] = (1 << flat[1]);
402 	size[0] = (patch_cp[0] / 2) * step[0] + 1;
403 	size[1] = (patch_cp[1] / 2) * step[1] + 1;
404 
405 	if (size[0]*size[1] > MAX_Q3BSP_CM_PATCH_VERTS) {
406 		Com_Error (ERR_DROP, "CM_Q3BSP_CreatePatch: patch has too many vertices");
407 		return;
408 	}
409 
410 	// Fill in
411 	Patch_Evaluate2 (verts, patch_cp, step, points);
412 
413 	patch->brushes = brush = cm_q3_brushes + cm_q3_numBrushes;
414 	patch->numBrushes = 0;
415 
416 	ClearBounds (patch->absMins, patch->absMaxs);
417 
418 	// Create a set of brushes
419     for (v=0 ; v<size[1]-1 ; v++) {
420 		for (u=0 ; u<size[0]-1 ; u++) {
421 			if (cm_q3_numBrushes >= MAX_Q3BSP_CM_BRUSHES)
422 				Com_Error (ERR_DROP, "CM_Q3BSP_CreatePatch: too many patch brushes");
423 
424 			i = v * size[0] + u;
425 			Vec3Copy (points[i], tverts[0]);
426 			Vec3Copy (points[i + size[0]], tverts[1]);
427 			Vec3Copy (points[i + 1], tverts[2]);
428 			Vec3Copy (points[i + size[0] + 1], tverts[3]);
429 
430 			// Add to bounds
431 			AddPointToBounds (tverts[0], patch->absMins, patch->absMaxs);
432 			AddPointToBounds (tverts[1], patch->absMins, patch->absMaxs);
433 			AddPointToBounds (tverts[2], patch->absMins, patch->absMaxs);
434 			AddPointToBounds (tverts[3], patch->absMins, patch->absMaxs);
435 
436 			PlaneFromPoints (tverts, &mainplane);
437 
438 			// Create two brushes
439 			CM_Q3BSP_CreateBrush (brush, tverts, patch->surface);
440 
441 			brush->contents = patch->surface->contents;
442 			brush++;
443 			cm_q3_numBrushes++;
444 			patch->numBrushes++;
445 
446 			Vec3Copy (tverts[2], tverts2[0]);
447 			Vec3Copy (tverts[1], tverts2[1]);
448 			Vec3Copy (tverts[3], tverts2[2]);
449 			CM_Q3BSP_CreateBrush (brush, tverts2, patch->surface);
450 
451 			brush->contents = patch->surface->contents;
452 			brush++;
453 			cm_q3_numBrushes++;
454 			patch->numBrushes++;
455 		}
456     }
457 }
458 
459 // ==========================================================================
460 
461 /*
462 =================
463 CM_Q3BSP_CreatePatchesForLeafs
464 =================
465 */
CM_Q3BSP_CreatePatchesForLeafs(void)466 static void CM_Q3BSP_CreatePatchesForLeafs (void)
467 {
468 	int				i, j, k;
469 	cleaf_t			*leaf;
470 	cface_t			*face;
471 	cBspSurface_t	*surf;
472 	cpatch_t		*patch;
473 	int				checkout[MAX_Q3BSP_CM_FACES];
474 
475 	memset (checkout, -1, sizeof(int)*MAX_Q3BSP_CM_FACES);
476 
477 	for (i=0, leaf=cm_q3_leafs ; i<cm_q3_numLeafs ; i++, leaf++) {
478 		leaf->numLeafPatches = 0;
479 		leaf->firstLeafPatch = cm_q3_numLeafPatches;
480 
481 		if (leaf->cluster == -1)
482 			continue;
483 
484 		for (j=0 ; j<leaf->numLeafFaces ; j++) {
485 			k = leaf->firstLeafFace + j;
486 			if (k >= cm_q3_numLeafFaces)
487 				break;
488 
489 			k = cm_q3_leafFaces[k];
490 			face = &cm_q3_mapFaces[k];
491 
492 			if (face->faceType != FACETYPE_PATCH || face->numVerts <= 0)
493 				continue;
494 			if (face->patch_cp[0] <= 0 || face->patch_cp[1] <= 0)
495 				continue;
496 			if (face->shaderNum < 0 || face->shaderNum >= cm_q3_numShaderRefs)
497 				continue;
498 
499 			surf = &cm_q3_surfaces[face->shaderNum];
500 			if (!surf->contents || surf->flags & SHREF_NONSOLID)
501 				continue;
502 
503 			if (cm_q3_numLeafPatches >= MAX_Q3BSP_CM_LEAFFACES)
504 				Com_Error (ERR_DROP, "CM_Q3BSP_CreatePatchesForLeafs: map has too many faces");
505 
506 			// The patch was already built
507 			if (checkout[k] != -1) {
508 				cm_q3_leafPatches[cm_q3_numLeafPatches] = checkout[k];
509 				patch = &cm_q3_patches[checkout[k]];
510 			}
511 			else {
512 				if (cm_q3_numPatches >= MAX_Q3BSP_CM_PATCHES)
513 					Com_Error (ERR_DROP, "CM_Q3BSP_CreatePatchesForLeafs: map has too many patches");
514 
515 				patch = &cm_q3_patches[cm_q3_numPatches];
516 				patch->surface = surf;
517 				cm_q3_leafPatches[cm_q3_numLeafPatches] = cm_q3_numPatches;
518 				checkout[k] = cm_q3_numPatches++;
519 
520 				CM_Q3BSP_CreatePatch (patch, face->numVerts, cm_q3_mapVerts + face->firstVert, face->patch_cp);
521 			}
522 
523 			leaf->contents |= patch->surface->contents;
524 			leaf->numLeafPatches++;
525 
526 			cm_q3_numLeafPatches++;
527 		}
528 	}
529 }
530 
531 /*
532 =============================================================================
533 
534 	QUAKE3 BSP LOADING
535 
536 =============================================================================
537 */
538 
539 /*
540 =================
541 CM_Q3BSP_LoadVertexes
542 =================
543 */
CM_Q3BSP_LoadVertexes(dQ3BspLump_t * l)544 static void CM_Q3BSP_LoadVertexes (dQ3BspLump_t *l)
545 {
546 	dQ3BspVertex_t	*in;
547 	vec4_t			*out;
548 	int				i;
549 
550 	// Check lump size
551 	in = (void *)(cm_q3_mapBuffer + l->fileOfs);
552 	if (l->fileLen % sizeof (*in))
553 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadVertexes: funny lump size");
554 
555 	// Check data size
556 	cm_q3_numVertexes = l->fileLen / sizeof (*in);
557 	if (cm_q3_numVertexes > MAX_Q3BSP_CM_VERTEXES)
558 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadVertexes: Map has too many vertexes");
559 	cm_q3_mapVerts = out = Mem_AllocExt (cm_q3_numVertexes * sizeof (*out), qFalse);
560 
561 	// Byte swap
562 	for (i=0 ; i<cm_q3_numVertexes ; i++, in++) {
563 		out[i][0] = LittleFloat (in->point[0]);
564 		out[i][1] = LittleFloat (in->point[1]);
565 		out[i][2] = LittleFloat (in->point[2]);
566 	}
567 }
568 
569 
570 /*
571 =================
572 CM_Q3BSP_LoadFaces
573 =================
574 */
CM_Q3BSP_LoadFaces(dQ3BspLump_t * l)575 static void CM_Q3BSP_LoadFaces (dQ3BspLump_t *l)
576 {
577 	dQ3BspFace_t	*in;
578 	cface_t			*out;
579 	int				i;
580 
581 	// Check lump size
582 	in = (void *)(cm_q3_mapBuffer + l->fileOfs);
583 	if (l->fileLen % sizeof (*in))
584 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadFaces: funny lump size");
585 
586 	// Check data size
587 	cm_q3_numFaces = l->fileLen / sizeof (*in);
588 	if (cm_q3_numFaces > MAX_Q3BSP_CM_FACES)
589 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadFaces: Map has too many faces");
590 	cm_q3_mapFaces = out = Mem_AllocExt (cm_q3_numFaces * sizeof (*out), qFalse);
591 
592 	// Byte swap
593 	for (i=0 ; i<cm_q3_numFaces ; i++, in++, out++) {
594 		out->faceType = LittleLong (in->faceType);
595 		out->shaderNum = LittleLong (in->shaderNum);
596 
597 		out->numVerts = LittleLong (in->numVerts);
598 		out->firstVert = LittleLong (in->firstVert);
599 
600 		out->patch_cp[0] = LittleLong (in->patch_cp[0]);
601 		out->patch_cp[1] = LittleLong (in->patch_cp[1]);
602 	}
603 }
604 
605 
606 /*
607 =================
608 CM_Q3BSP_LoadLeafFaces
609 =================
610 */
CM_Q3BSP_LoadLeafFaces(dQ3BspLump_t * l)611 static void CM_Q3BSP_LoadLeafFaces (dQ3BspLump_t *l)
612 {
613 	int		i, j;
614 	int		*in;
615 	int		*out;
616 
617 	// Check lump size
618 	in = (void *)(cm_q3_mapBuffer + l->fileOfs);
619 	if (l->fileLen % sizeof (*in))
620 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadLeafFaces: funny lump size");
621 
622 	// Check data size
623 	cm_q3_numLeafFaces = l->fileLen / sizeof(*in);
624 	if (cm_q3_numLeafFaces > MAX_Q3BSP_CM_LEAFFACES)
625 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadLeafFaces: Map has too many leaffaces");
626 	cm_q3_leafFaces = out = Mem_AllocExt (cm_q3_numLeafFaces*sizeof(*out), qFalse);
627 
628 	// Byte swap
629 	for (i=0 ; i<cm_q3_numLeafFaces ; i++) {
630 		j = LittleLong (in[i]);
631 		if (j < 0 ||  j >= cm_q3_numFaces)
632 			Com_Error (ERR_DROP, "CMod_LoadLeafFaces: bad surface number");
633 
634 		out[i] = j;
635 	}
636 }
637 
638 
639 /*
640 =================
641 CM_Q3BSP_LoadSubmodels
642 =================
643 */
CM_Q3BSP_LoadSubmodels(dQ3BspLump_t * l)644 static void CM_Q3BSP_LoadSubmodels (dQ3BspLump_t *l)
645 {
646 	dQ3BspModel_t	*in;
647 	cBspModel_t		*out;
648 	cleaf_t			*bleaf;
649 	int				*leafbrush;
650 	int				i, j;
651 
652 	// Check lump size
653 	in = (void *)(cm_q3_mapBuffer + l->fileOfs);
654 	if (l->fileLen % sizeof (*in))
655 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadSubmodels: funny lump size");
656 
657 	// Check data size
658 	cm_numCModels = l->fileLen / sizeof (*in);
659 	if (cm_numCModels < 1)
660 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadSubmodels: Map with no models");
661 	else if (cm_numCModels > MAX_Q3BSP_CM_MODELS)
662 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadSubmodels: Map has too many models");
663 
664 	// Byte swap
665 	for (i=0 ; i<cm_numCModels ; i++, in++, out++) {
666 		out = &cm_mapCModels[i];
667 
668 		if (!i) {
669 			out->headNode = 0;
670 		}
671 		else {
672 			out->headNode = -1 - cm_q3_numLeafs;
673 
674 			bleaf = &cm_q3_leafs[cm_q3_numLeafs++];
675 			bleaf->numLeafBrushes = LittleLong (in->numBrushes);
676 			bleaf->firstLeafBrush = cm_q3_numLeafBrushes;
677 			bleaf->contents = 0;
678 
679 			leafbrush = &cm_q3_leafBrushes[cm_q3_numLeafBrushes];
680 			for (j=0 ; j<bleaf->numLeafBrushes ; j++, leafbrush++) {
681 				*leafbrush = LittleLong (in->firstBrush) + j;
682 				bleaf->contents |= cm_q3_brushes[*leafbrush].contents;
683 			}
684 
685 			cm_q3_numLeafBrushes += bleaf->numLeafBrushes;
686 		}
687 
688 		// Spread the mins / maxs by a pixel
689 		for (j=0 ; j<3 ; j++) {
690 			out->mins[j] = LittleFloat (in->mins[j]) - 1;
691 			out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
692 		}
693 	}
694 }
695 
696 
697 /*
698 =================
699 CM_Q3BSP_LoadSurfaces
700 =================
701 */
CM_Q3BSP_LoadSurfaces(dQ3BspLump_t * l)702 static void CM_Q3BSP_LoadSurfaces (dQ3BspLump_t *l)
703 {
704 	dQ3BspShaderRef_t	*in;
705 	cBspSurface_t		*out;
706 	int					i;
707 
708 	// Sanity check lump size
709 	in = (void *)(cm_q3_mapBuffer + l->fileOfs);
710 	if (l->fileLen % sizeof(*in))
711 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadSurfaces: funny lump size");
712 
713 	// Find the size and allocate
714 	cm_q3_numShaderRefs = l->fileLen / sizeof(*in);
715 	if (cm_q3_numShaderRefs < 1)
716 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadSurfaces: Map with no shaders");
717 	else if (cm_q3_numShaderRefs > MAX_Q3BSP_CM_SHADERS)
718 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadSurfaces: Map has too many shaders");
719 	cm_q3_surfaces = Mem_PoolAlloc (sizeof(cBspSurface_t) * cm_q3_numShaderRefs, com_cmodelSysPool, 0);
720 
721 	// Byte swap
722 	out = cm_q3_surfaces;
723 	for (i=0 ; i<cm_q3_numShaderRefs ; i++, in++, out++) {
724 		out->flags = LittleLong (in->flags);
725 		out->contents = LittleLong (in->contents);
726 	}
727 }
728 
729 
730 /*
731 =================
732 CM_Q3BSP_LoadNodes
733 =================
734 */
CM_Q3BSP_LoadNodes(dQ3BspLump_t * l)735 static void CM_Q3BSP_LoadNodes (dQ3BspLump_t *l)
736 {
737 	dQ3BspNode_t	*in;
738 	int				child;
739 	cnode_t			*out;
740 	int				i, j;
741 
742 	// Sanity check lump size
743 	in = (void *)(cm_q3_mapBuffer + l->fileOfs);
744 	if (l->fileLen % sizeof(*in))
745 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadNodes: funny lump size");
746 
747 	// Find the size and allocate (with extra for box hull)
748 	cm_q3_numNodes = l->fileLen / sizeof (*in);
749 	if (cm_q3_numNodes < 1)
750 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadNodes: Map has no nodes");
751 	else if (cm_q3_numNodes > MAX_Q3BSP_CM_NODES)
752 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadNodes: Map has too many nodes");
753 	cm_q3_nodes = Mem_PoolAlloc (sizeof(cnode_t) * (cm_q3_numNodes+6), com_cmodelSysPool, 0);
754 
755 	// Byte swap
756 	out = cm_q3_nodes;
757 	for (i=0 ; i<cm_q3_numNodes ; i++, out++, in++) {
758 		out->plane = cm_q3_planes + LittleLong (in->planeNum);
759 		for (j=0 ; j<2 ; j++) {
760 			child = LittleLong (in->children[j]);
761 			out->children[j] = child;
762 		}
763 	}
764 }
765 
766 
767 /*
768 =================
769 CM_Q3BSP_LoadBrushes
770 =================
771 */
CM_Q3BSP_LoadBrushes(dQ3BspLump_t * l)772 static void CM_Q3BSP_LoadBrushes (dQ3BspLump_t *l)
773 {
774 	dQ3BspBrush_t	*in;
775 	cbrush_t		*out;
776 	int				i, shaderRef;
777 
778 	// Check lump size
779 	in = (void *)(cm_q3_mapBuffer + l->fileOfs);
780 	if (l->fileLen % sizeof(*in))
781 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadBrushes: funny lump size");
782 
783 	// Check data size
784 	cm_q3_numBrushes = l->fileLen / sizeof(*in);
785 	if (cm_q3_numBrushes > MAX_Q3BSP_CM_BRUSHES)
786 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadBrushes: Map has too many brushes");
787 
788 	// Byte swap
789 	out = cm_q3_brushes;
790 	for (i=0 ; i<cm_q3_numBrushes ; i++, out++, in++) {
791 		shaderRef = LittleLong (in->shaderNum);
792 		out->contents = cm_q3_surfaces[shaderRef].contents;
793 		out->firstBrushSide = LittleLong (in->firstSide);
794 		out->numSides = LittleLong (in->numSides);
795 	}
796 }
797 
798 
799 /*
800 =================
801 CM_Q3BSP_LoadLeafs
802 =================
803 */
CM_Q3BSP_LoadLeafs(dQ3BspLump_t * l)804 static void CM_Q3BSP_LoadLeafs (dQ3BspLump_t *l)
805 {
806 	int				i, j;
807 	cleaf_t			*out;
808 	dQ3BspLeaf_t 	*in;
809 	cbrush_t		*brush;
810 
811 	// Check lump size
812 	in = (void *)(cm_q3_mapBuffer + l->fileOfs);
813 	if (l->fileLen % sizeof(*in))
814 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadLeafs: funny lump size");
815 
816 	// Check data size
817 	cm_q3_numLeafs = l->fileLen / sizeof(*in);
818 	if (cm_q3_numLeafs < 1)
819 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadLeafs: Map with no leafs");
820 	else if (cm_q3_numLeafs > MAX_Q3BSP_CM_LEAFS)
821 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadLeafs: Map has too many leafs");
822 
823 	// Byte swap
824 	out = cm_q3_leafs;
825 	cm_q3_emptyLeaf = -1;
826 
827 	for (i=0 ; i<cm_q3_numLeafs ; i++, in++, out++) {
828 		out->cluster = LittleLong (in->cluster);
829 		out->area = LittleLong (in->area) + 1;
830 		out->firstLeafFace = LittleLong (in->firstLeafFace);
831 		out->numLeafFaces = LittleLong (in->numLeafFaces);
832 		out->contents = 0;
833 		out->firstLeafBrush = LittleLong (in->firstLeafBrush);
834 		out->numLeafBrushes = LittleLong (in->numLeafBrushes);
835 
836 		for (j=0 ; j<out->numLeafBrushes ; j++) {
837 			brush = &cm_q3_brushes[cm_q3_leafBrushes[out->firstLeafBrush+j]];
838 			out->contents |= brush->contents;
839 		}
840 
841 		if (out->area >= cm_q3_numAreas)
842 			cm_q3_numAreas = out->area + 1;
843 
844 		if (!out->contents)
845 			cm_q3_emptyLeaf = i;
846 	}
847 
848 	// If map doesn't have an empty leaf - force one
849 	if (cm_q3_emptyLeaf == -1) {
850 		if (cm_q3_numLeafs >= MAX_Q3BSP_CM_LEAFS-1)
851 			Com_Error (ERR_DROP, "CM_Q3BSP_LoadLeafs: Map does not have an empty leaf");
852 
853 		out->cluster = -1;
854 		out->area = -1;
855 		out->numLeafBrushes = 0;
856 		out->contents = 0;
857 		out->firstLeafBrush = 0;
858 
859 		Com_DevPrintf (0, "CM_Q3BSP_LoadLeafs: Forcing an empty leaf: %i\n", cm_q3_numLeafs);
860 		cm_q3_emptyLeaf = cm_q3_numLeafs++;
861 	}
862 }
863 
864 
865 /*
866 =================
867 CM_Q3BSP_LoadPlanes
868 =================
869 */
CM_Q3BSP_LoadPlanes(dQ3BspLump_t * l)870 static void CM_Q3BSP_LoadPlanes (dQ3BspLump_t *l)
871 {
872 	int				i;
873 	cBspPlane_t		*out;
874 	dQ3BspPlane_t 	*in;
875 
876 	// Sanity check lump size
877 	in = (void *)(cm_q3_mapBuffer + l->fileOfs);
878 	if (l->fileLen % sizeof(*in))
879 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadPlanes: funny lump size");
880 
881 	// Find the size and allocate (with extra for box hull)
882 	cm_q3_numPlanes = l->fileLen / sizeof(*in);
883 	if (cm_q3_numPlanes < 1)
884 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadPlanes: Map with no planes");
885 	else if (cm_q3_numPlanes > MAX_Q3BSP_CM_PLANES)
886 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadPlanes: Map has too many planes");
887 	cm_q3_planes = Mem_PoolAlloc (sizeof(cBspPlane_t) * (MAX_Q3BSP_CM_PLANES+12), com_cmodelSysPool, 0);	// FIXME
888 
889 	// Byte swap
890 	out = cm_q3_planes;
891 	for (i=0 ; i<cm_q3_numPlanes ; i++, in++, out++) {
892 		out->normal[0] = LittleFloat (in->normal[0]);
893 		out->normal[1] = LittleFloat (in->normal[1]);
894 		out->normal[2] = LittleFloat (in->normal[2]);
895 
896 		out->dist = LittleFloat (in->dist);
897 
898 		CategorizePlane (out);
899 	}
900 }
901 
902 
903 /*
904 =================
905 CM_Q3BSP_LoadLeafBrushes
906 =================
907 */
CM_Q3BSP_LoadLeafBrushes(dQ3BspLump_t * l)908 static void CM_Q3BSP_LoadLeafBrushes (dQ3BspLump_t *l)
909 {
910 	int			i;
911 	int			*out;
912 	int		 	*in;
913 
914 	// Check lump size
915 	in = (void *)(cm_q3_mapBuffer + l->fileOfs);
916 	if (l->fileLen % sizeof(*in))
917 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadLeafBrushes: funny lump size");
918 
919 	// Check data size
920 	cm_q3_numLeafBrushes = l->fileLen / sizeof(*in);
921 	if (cm_q3_numLeafBrushes < 1)
922 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadLeafBrushes: Map with no planes");
923 	else if (cm_q3_numLeafBrushes > MAX_Q3BSP_CM_LEAFBRUSHES)
924 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadLeafBrushes: Map has too many leafbrushes");
925 
926 	// Byte swap
927 	out = cm_q3_leafBrushes;
928 	for ( i=0 ; i<cm_q3_numLeafBrushes ; i++, in++, out++)
929 		*out = LittleLong (*in);
930 }
931 
932 
933 /*
934 =================
935 CM_Q3BSP_LoadBrushSides
936 =================
937 */
CM_Q3BSP_LoadBrushSides(dQ3BspLump_t * l)938 static void CM_Q3BSP_LoadBrushSides (dQ3BspLump_t *l)
939 {
940 	int					i, j;
941 	cbrushside_t		*out;
942 	dQ3BspBrushSide_t 	*in;
943 
944 	// Check lump size
945 	in = (void *)(cm_q3_mapBuffer + l->fileOfs);
946 	if (l->fileLen % sizeof(*in))
947 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadBrushSides: funny lump size");
948 
949 	// Check data size
950 	cm_q3_numBrushSides = l->fileLen / sizeof(*in);
951 	if (cm_q3_numBrushSides > MAX_Q3BSP_CM_BRUSHSIDES)
952 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadBrushSides: Map has too many brushSides");
953 
954 	// Byte swap
955 	out = cm_q3_brushSides;
956 	for (i=0 ; i<cm_q3_numBrushSides ; i++, in++, out++) {
957 		out->plane = cm_q3_planes + LittleLong (in->planeNum);
958 		j = LittleLong (in->shaderNum);
959 		if (j >= cm_q3_numShaderRefs)
960 			Com_Error (ERR_DROP, "CM_Q3BSP_LoadBrushSides: Bad brushside texinfo");
961 		out->surface = &cm_q3_surfaces[j];
962 	}
963 }
964 
965 
966 /*
967 =================
968 CM_Q3BSP_LoadVisibility
969 =================
970 */
CM_Q3BSP_LoadVisibility(dQ3BspLump_t * l)971 static void CM_Q3BSP_LoadVisibility (dQ3BspLump_t *l)
972 {
973 	// Check data size
974 	cm_q3_numVisibility = l->fileLen;
975 	if (l->fileLen > MAX_Q3BSP_CM_VISIBILITY)
976 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadVisibility: Map has too large visibility lump");
977 
978 	// Byte swap
979 	memcpy (cm_q3_visData, cm_q3_mapBuffer + l->fileOfs, l->fileLen);
980 
981 	cm_q3_visData->numClusters = LittleLong (cm_q3_visData->numClusters);
982 	cm_q3_visData->rowSize = LittleLong (cm_q3_visData->rowSize);
983 }
984 
985 
986 /*
987 =================
988 CM_Q3BSP_LoadEntityString
989 =================
990 */
CM_Q3BSP_LoadEntityString(dQ3BspLump_t * l)991 static void CM_Q3BSP_LoadEntityString (dQ3BspLump_t *l)
992 {
993 	// Find the size and allocate (with extra for NULL termination)
994 	cm_q3_numEntityChars = l->fileLen;
995 	if (l->fileLen > MAX_Q3BSP_CM_ENTSTRING)
996 		Com_Error (ERR_DROP, "CM_Q3BSP_LoadEntityString: Map has too large entity lump");
997 	cm_q3_entityString = Mem_PoolAlloc (sizeof(char) * (cm_q3_numEntityChars+1), com_cmodelSysPool, 0);
998 
999 	// Copy data
1000 	memcpy (cm_q3_entityString, cm_q3_mapBuffer + l->fileOfs, l->fileLen);
1001 }
1002 
1003 
1004 /*
1005 =================
1006 CM_Q3BSP_CalcPHS
1007 =================
1008 */
CM_Q3BSP_CalcPHS(void)1009 static void CM_Q3BSP_CalcPHS (void)
1010 {
1011 	int		rowbytes, rowwords;
1012 	int		i, j, k, l, index;
1013 	int		bitbyte;
1014 	uint32	*dest, *src;
1015 	byte	*scan;
1016 	int		count, vcount;
1017 	int		numClusters;
1018 
1019 	Com_DevPrintf (0, "CM_Q3BSP_CalcPHS: Building PHS...\n");
1020 
1021 	rowwords = cm_q3_visData->rowSize / sizeof(long);
1022 	rowbytes = cm_q3_visData->rowSize;
1023 
1024 	memset (cm_q3_hearData, 0, MAX_Q3BSP_CM_VISIBILITY);
1025 
1026 	cm_q3_hearData->rowSize = cm_q3_visData->rowSize;
1027 	cm_q3_hearData->numClusters = numClusters = cm_q3_visData->numClusters;
1028 
1029 	vcount = 0;
1030 	for (i=0 ; i<numClusters ; i++) {
1031 		scan = CM_Q3BSP_ClusterPVS (i);
1032 		for (j=0 ; j<numClusters ; j++) {
1033 			if (scan[j>>3] & (1<<(j&7)))
1034 				vcount++;
1035 		}
1036 	}
1037 
1038 	count = 0;
1039 	scan = (byte *)cm_q3_visData->data;
1040 	dest = (uint32 *)cm_q3_hearData->data;
1041 
1042 	for (i=0 ; i<numClusters ; i++, dest += rowwords, scan += rowbytes) {
1043 		memcpy (dest, scan, rowbytes);
1044 		for (j=0 ; j<rowbytes ; j++) {
1045 			bitbyte = scan[j];
1046 			if (!bitbyte)
1047 				continue;
1048 			for (k=0 ; k<8 ; k++) {
1049 				if (!(bitbyte & (1<<k)))
1050 					continue;
1051 
1052 				// OR this pvs row into the phs
1053 				index = (j<<3) + k;
1054 				if (index >= numClusters)
1055 					Com_Error (ERR_DROP, "CM_Q3BSP_CalcPHS: Bad bit in PVS");	// pad bits should be 0
1056 				src = (unsigned *)((byte*)cm_q3_visData->data) + index*rowwords;
1057 				for (l=0 ; l<rowwords ; l++)
1058 					dest[l] |= src[l];
1059 			}
1060 		}
1061 		for (j=0 ; j<numClusters ; j++)
1062 			if (((byte *)dest)[j>>3] & (1<<(j&7)))
1063 				count++;
1064 	}
1065 
1066 	Com_DevPrintf (0, "CM_Q3BSP_CalcPHS: Average clusters visible / hearable / total: %i / %i / %i\n"
1067 		, vcount ? vcount/numClusters : 0,
1068 		count ? count/numClusters : 0, numClusters);
1069 }
1070 
1071 // ==========================================================================
1072 
1073 /*
1074 =================
1075 CM_Q3BSP_LoadMap
1076 =================
1077 */
CM_Q3BSP_LoadMap(uint32 * buffer)1078 cBspModel_t *CM_Q3BSP_LoadMap (uint32 *buffer)
1079 {
1080 	dQ3BspHeader_t	header;
1081 	int				i;
1082 
1083 	//
1084 	// Allocate space
1085 	//
1086 	cm_q3_areaPortals = Mem_PoolAlloc (sizeof(careaportal_t) * MAX_Q3BSP_CM_AREAPORTALS, com_cmodelSysPool, 0);
1087 	cm_q3_areas = Mem_PoolAlloc (sizeof(carea_t) * MAX_Q3BSP_CM_AREAS, com_cmodelSysPool, 0);
1088 	cm_q3_brushes = Mem_PoolAlloc (sizeof(cbrush_t) * (MAX_Q3BSP_CM_BRUSHES+1), com_cmodelSysPool, 0);				// extra for box hull
1089 	cm_q3_brushSides = Mem_PoolAlloc (sizeof(cbrushside_t) * (MAX_Q3BSP_CM_BRUSHSIDES+6), com_cmodelSysPool, 0);	// extra for box hull
1090 	cm_q3_hearData = Mem_PoolAlloc (sizeof(byte) * MAX_Q3BSP_CM_VISIBILITY, com_cmodelSysPool, 0);
1091 	cm_q3_leafBrushes = Mem_PoolAlloc (sizeof(int) * (MAX_Q3BSP_CM_LEAFBRUSHES+1), com_cmodelSysPool, 0);			// extra for box hull
1092 	cm_q3_leafPatches = Mem_PoolAlloc (sizeof(int) * MAX_Q3BSP_CM_LEAFFACES, com_cmodelSysPool, 0);
1093 	cm_q3_leafs = Mem_PoolAlloc (sizeof(cleaf_t) * MAX_Q3BSP_CM_LEAFS, com_cmodelSysPool, 0);
1094 	cm_q3_nullRow = Mem_PoolAllocExt (sizeof(byte) * (MAX_Q3BSP_CM_LEAFS / 8), qFalse, com_cmodelSysPool, 0);
1095 	cm_q3_patches = Mem_PoolAlloc (sizeof(cpatch_t) * MAX_Q3BSP_CM_PATCHES, com_cmodelSysPool, 0);
1096 	cm_q3_visData = Mem_PoolAlloc (sizeof(byte) * MAX_Q3BSP_CM_VISIBILITY, com_cmodelSysPool, 0);
1097 
1098 	// Default values
1099 	memset (cm_q3_nullRow, 255, MAX_Q3BSP_CM_LEAFS / 8);
1100 
1101 	//
1102 	// Byte swap lumps
1103 	//
1104 	header = *(dQ3BspHeader_t *)buffer;
1105 	for (i=0 ; i<sizeof (dQ3BspHeader_t)/4 ; i++)
1106 		((int *)&header)[i] = LittleLong (((int *)&header)[i]);
1107 	cm_q3_mapBuffer = (byte *)buffer;
1108 
1109 	//
1110 	// Load into heap
1111 	//
1112 	CM_Q3BSP_LoadSurfaces		(&header.lumps[Q3BSP_LUMP_SHADERREFS]);
1113 	CM_Q3BSP_LoadPlanes			(&header.lumps[Q3BSP_LUMP_PLANES]);
1114 	CM_Q3BSP_LoadLeafBrushes	(&header.lumps[Q3BSP_LUMP_LEAFBRUSHES]);
1115 	CM_Q3BSP_LoadBrushes		(&header.lumps[Q3BSP_LUMP_BRUSHES]);
1116 	CM_Q3BSP_LoadBrushSides		(&header.lumps[Q3BSP_LUMP_BRUSHSIDES]);
1117 	CM_Q3BSP_LoadVertexes		(&header.lumps[Q3BSP_LUMP_VERTEXES]);
1118 	CM_Q3BSP_LoadFaces			(&header.lumps[Q3BSP_LUMP_FACES]);
1119 	CM_Q3BSP_LoadLeafFaces		(&header.lumps[Q3BSP_LUMP_LEAFFACES]);
1120 	CM_Q3BSP_LoadLeafs			(&header.lumps[Q3BSP_LUMP_LEAFS]);
1121 	CM_Q3BSP_LoadNodes			(&header.lumps[Q3BSP_LUMP_NODES]);
1122 	CM_Q3BSP_LoadSubmodels		(&header.lumps[Q3BSP_LUMP_MODELS]);
1123 	CM_Q3BSP_LoadVisibility		(&header.lumps[Q3BSP_LUMP_VISIBILITY]);
1124 	CM_Q3BSP_LoadEntityString	(&header.lumps[Q3BSP_LUMP_ENTITIES]);
1125 
1126 	CM_Q3BSP_CreatePatchesForLeafs ();
1127 
1128 	CM_Q3BSP_InitBoxHull ();
1129 	CM_Q3BSP_PrepMap ();
1130 
1131 	CM_Q3BSP_CalcPHS ();
1132 
1133 	if (cm_q3_mapVerts)
1134 		Mem_Free (cm_q3_mapVerts);
1135 	if (cm_q3_mapFaces)
1136 		Mem_Free (cm_q3_mapFaces);
1137 	if (cm_q3_leafFaces)
1138 		Mem_Free (cm_q3_leafFaces);
1139 
1140 	return &cm_mapCModels[0];
1141 }
1142 
1143 
1144 /*
1145 ==================
1146 CM_Q3BSP_PrepMap
1147 ==================
1148 */
CM_Q3BSP_PrepMap(void)1149 void CM_Q3BSP_PrepMap (void)
1150 {
1151 	CM_Q3BSP_FloodAreaConnections ();
1152 }
1153 
1154 
1155 /*
1156 ==================
1157 CM_Q3BSP_UnloadMap
1158 ==================
1159 */
CM_Q3BSP_UnloadMap(void)1160 void CM_Q3BSP_UnloadMap (void)
1161 {
1162 	cm_q3_areaPortals = NULL;
1163 	cm_q3_areas = NULL;
1164 	cm_q3_brushes = NULL;
1165 	cm_q3_brushSides = NULL;
1166 	cm_q3_entityString = cm_q3_emptyEntityString;
1167 	cm_q3_hearData = NULL;
1168 	cm_q3_leafBrushes = NULL;
1169 	cm_q3_leafPatches = NULL;
1170 	cm_q3_leafs = NULL;
1171 	cm_q3_nodes = NULL;
1172 	cm_q3_nullRow = NULL;
1173 	cm_q3_patches = NULL;
1174 	cm_q3_planes = NULL;
1175 	cm_q3_surfaces = NULL;
1176 	cm_q3_visData = NULL;
1177 
1178 	cm_q3_numEntityChars = 0;
1179 	cm_q3_numBrushSides = 0;
1180 	cm_q3_numShaderRefs = 0;
1181 	cm_q3_numPlanes = 0;
1182 	cm_q3_numNodes = 0;
1183 	cm_q3_numLeafs = 1;
1184 	cm_q3_numLeafBrushes = 0;
1185 	cm_q3_numBrushes = 0;
1186 	cm_q3_numVisibility = 0;
1187 	cm_q3_numAreaPortals = 1;
1188 	cm_q3_numAreas = 1;
1189 	cm_q3_numPatches = 0;
1190 	cm_q3_numLeafPatches = 0;
1191 	cm_q3_numVertexes = 0;
1192 	cm_q3_numFaces = 0;
1193 	cm_q3_numLeafFaces = 0;
1194 }
1195 
1196 /*
1197 =============================================================================
1198 
1199 	QUAKE3 BSP INFORMATION
1200 
1201 =============================================================================
1202 */
1203 
1204 /*
1205 ==================
1206 CM_Q3BSP_EntityString
1207 ==================
1208 */
CM_Q3BSP_EntityString(void)1209 char *CM_Q3BSP_EntityString (void)
1210 {
1211 	return cm_q3_entityString;
1212 }
1213 
1214 
1215 /*
1216 ==================
1217 CM_Q3BSP_SurfRName
1218 ==================
1219 */
CM_Q3BSP_SurfRName(int texNum)1220 char *CM_Q3BSP_SurfRName (int texNum)
1221 {
1222 	// FIXME
1223 	return NULL;
1224 }
1225 
1226 
1227 /*
1228 ==================
1229 CM_Q3BSP_NumClusters
1230 ==================
1231 */
CM_Q3BSP_NumClusters(void)1232 int CM_Q3BSP_NumClusters (void)
1233 {
1234 	return cm_q3_visData ? cm_q3_visData->numClusters : 1;
1235 }
1236 
1237 /*
1238 ==================
1239 CM_Q3BSP_NumTexInfo
1240 ==================
1241 */
CM_Q3BSP_NumTexInfo(void)1242 int CM_Q3BSP_NumTexInfo (void)
1243 {
1244 	// FIXME
1245 	return 0;
1246 }
1247