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_q2_main.c
22 // Quake2 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_q2_local.h"
28
29 static byte *cm_q2_mapBuffer;
30
31 static int cm_q2_numEntityChars;
32 static char cm_q2_emptyEntityString[1];
33 static char *cm_q2_entityString;
34
35 static int cm_q2_numTexInfo;
36 static cQ2MapSurface_t *cm_q2_surfaces;
37 static int cm_q2_numTexInfoUnique;
38 static cQ2MapSurface_t **cm_q2_surfacesUnique;
39
40 int cm_q2_numNodes;
41 cQ2BspNode_t *cm_q2_nodes;
42
43 int cm_q2_numBrushSides;
44 cQ2BspBrushSide_t *cm_q2_brushSides;
45
46 int cm_q2_numLeafs = 1; // allow leaf funcs to be called without a map
47 int cm_q2_emptyLeaf;
48 cQ2BspLeaf_t *cm_q2_leafs;
49
50 int cm_q2_numLeafBrushes;
51 uint16 *cm_q2_leafBrushes;
52
53 int cm_q2_numBrushes;
54 cQ2BspBrush_t *cm_q2_brushes;
55
56 int cm_q2_numAreas = 1;
57 cQ2BspArea_t *cm_q2_areas;
58
59 cQ2MapSurface_t cm_q2_nullSurface;
60
61 int cm_q2_numPlanes;
62 cBspPlane_t *cm_q2_planes;
63
64 int cm_q2_numVisibility;
65 dQ2BspVis_t *cm_q2_visData;
66
67 int cm_q2_numAreaPortals;
68 dQ2BspAreaPortal_t *cm_q2_areaPortals;
69 qBool *cm_q2_portalOpen;
70
71 int cm_q2_numClusters = 1;
72
73 /*
74 =============================================================================
75
76 QUAKE2 BSP LOADING
77
78 =============================================================================
79 */
80
81 /*
82 =================
83 CM_Q2BSP_LoadSurfaces
84 =================
85 */
CM_Q2BSP_LoadSurfaces(dQ2BspLump_t * l)86 static void CM_Q2BSP_LoadSurfaces (dQ2BspLump_t *l)
87 {
88 dQ2BspTexInfo_t *in;
89 cQ2MapSurface_t *out;
90 int i, j;
91 int unique;
92
93 // Sanity check lump size
94 in = (void *)(cm_q2_mapBuffer + l->fileOfs);
95 if (l->fileLen % sizeof (*in))
96 Com_Error (ERR_DROP, "CM_Q2BSP_LoadSurfaces: funny lump size");
97
98 // Total
99 cm_q2_numTexInfo = l->fileLen / sizeof (*in);
100 if (cm_q2_numTexInfo < 1)
101 Com_Error (ERR_DROP, "CM_Q2BSP_LoadSurfaces: Map with no surfaces");
102 if (cm_q2_numTexInfo > Q2BSP_MAX_TEXINFO)
103 Com_Error (ERR_DROP, "CM_Q2BSP_LoadSurfaces: Map has too many surfaces");
104 cm_q2_surfaces = Mem_PoolAlloc (sizeof(cQ2MapSurface_t) * cm_q2_numTexInfo, com_cmodelSysPool, 0);
105
106 // Byte swap
107 out = cm_q2_surfaces;
108 for (i=0 ; i<cm_q2_numTexInfo ; i++, in++, out++) {
109 Q_strncpyz (out->c.name, in->texture, sizeof (out->c.name));
110 Q_strncpyz (out->rname, in->texture, sizeof (out->rname));
111 out->c.flags = LittleLong (in->flags);
112 out->c.value = LittleLong (in->value);
113 }
114
115 // Find the total unique
116 unique = 0;
117 for (i=0 ; i<cm_q2_numTexInfo ; i++) {
118 for (j=i-1 ; j>=0 ; j--) {
119 if (!Q_stricmp (cm_q2_surfaces[i].rname, cm_q2_surfaces[j].rname))
120 break;
121 }
122 if (j == -1)
123 unique++;
124 }
125
126 // Shouldn't really happen...
127 if (!unique)
128 return;
129
130 cm_q2_numTexInfoUnique = unique;
131 cm_q2_surfacesUnique = Mem_PoolAlloc (sizeof(cQ2MapSurface_t *) * cm_q2_numTexInfoUnique, com_cmodelSysPool, 0);
132 for (i=0, unique=0 ; i<cm_q2_numTexInfo ; i++) {
133 for (j=i-1 ; j>=0 ; j--) {
134 if (!Q_stricmp (cm_q2_surfaces[i].rname, cm_q2_surfaces[j].rname))
135 break;
136 }
137 if (j == -1)
138 cm_q2_surfacesUnique[unique++] = &cm_q2_surfaces[i];
139 }
140 }
141
142
143 /*
144 =================
145 CM_Q2BSP_LoadLeafs
146 =================
147 */
CM_Q2BSP_LoadLeafs(dQ2BspLump_t * l)148 static void CM_Q2BSP_LoadLeafs (dQ2BspLump_t *l)
149 {
150 int i;
151 cQ2BspLeaf_t *out;
152 dQ2BspLeaf_t *in;
153
154 // Sanity check lump size
155 in = (void *)(cm_q2_mapBuffer + l->fileOfs);
156 if (l->fileLen % sizeof (*in))
157 Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafs: funny lump size");
158
159 // Find the size and allocate (with extra for box hull)
160 cm_q2_numLeafs = l->fileLen / sizeof (*in);
161 if (cm_q2_numLeafs < 1)
162 Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafs: Map with no leafs");
163 if (cm_q2_numLeafs > Q2BSP_MAX_PLANES)
164 Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafs: Map has too many planes");
165 cm_q2_leafs = Mem_PoolAlloc (sizeof(cQ2BspLeaf_t) * (cm_q2_numLeafs+6), com_cmodelSysPool, 0);
166
167 // Byte swap
168 out = cm_q2_leafs;
169 cm_q2_numClusters = 0;
170
171 for (i=0 ; i<cm_q2_numLeafs ; i++, in++, out++) {
172 out->contents = LittleLong (in->contents);
173 out->cluster = LittleShort (in->cluster);
174 out->area = LittleShort (in->area);
175 out->firstLeafBrush = LittleShort (in->firstLeafBrush);
176 out->numLeafBrushes = LittleShort (in->numLeafBrushes);
177
178 if (out->cluster >= cm_q2_numClusters)
179 cm_q2_numClusters = out->cluster + 1;
180 }
181
182 if (cm_q2_leafs[0].contents != CONTENTS_SOLID)
183 Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafs: Map leaf 0 is not CONTENTS_SOLID");
184
185 cm_q2_emptyLeaf = -1;
186 for (i=1 ; i<cm_q2_numLeafs ; i++) {
187 if (!cm_q2_leafs[i].contents) {
188 cm_q2_emptyLeaf = i;
189 break;
190 }
191 }
192 if (cm_q2_emptyLeaf == -1)
193 Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafs: Map does not have an empty leaf");
194 }
195
196
197 /*
198 =================
199 CM_Q2BSP_LoadLeafBrushes
200 =================
201 */
CM_Q2BSP_LoadLeafBrushes(dQ2BspLump_t * l)202 static void CM_Q2BSP_LoadLeafBrushes (dQ2BspLump_t *l)
203 {
204 int i;
205 uint16 *out;
206 uint16 *in;
207
208 // Sanity check lump size
209 in = (void *)(cm_q2_mapBuffer + l->fileOfs);
210 if (l->fileLen % sizeof (*in))
211 Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafBrushes: funny lump size");
212
213 // Find the size and allocate (with extra for box hull)
214 cm_q2_numLeafBrushes = l->fileLen / sizeof (*in);
215 if (cm_q2_numLeafBrushes < 1)
216 Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafBrushes: Map with no planes");
217 if (cm_q2_numLeafBrushes > Q2BSP_MAX_LEAFBRUSHES)
218 Com_Error (ERR_DROP, "CM_Q2BSP_LoadLeafBrushes: Map has too many leafbrushes");
219 cm_q2_leafBrushes = Mem_PoolAlloc (sizeof(uint16) * (cm_q2_numLeafBrushes+1), com_cmodelSysPool, 0);
220
221 // Byte swap
222 out = cm_q2_leafBrushes;
223 for (i=0 ; i<cm_q2_numLeafBrushes ; i++, in++, out++)
224 *out = LittleShort (*in);
225 }
226
227
228 /*
229 =================
230 CM_Q2BSP_LoadPlanes
231 =================
232 */
CM_Q2BSP_LoadPlanes(dQ2BspLump_t * l)233 static void CM_Q2BSP_LoadPlanes (dQ2BspLump_t *l)
234 {
235 int i, j;
236 cBspPlane_t *out;
237 dQ2BspPlane_t *in;
238 int bits;
239
240 // Sanity check lump size
241 in = (void *)(cm_q2_mapBuffer + l->fileOfs);
242 if (l->fileLen % sizeof (*in))
243 Com_Error (ERR_DROP, "CM_Q2BSP_LoadPlanes: funny lump size");
244
245 // Find the size and allocate (with extra for box hull)
246 cm_q2_numPlanes = l->fileLen / sizeof (*in);
247 if (cm_q2_numPlanes < 1)
248 Com_Error (ERR_DROP, "CM_Q2BSP_LoadPlanes: Map with no planes");
249 if (cm_q2_numPlanes > Q2BSP_MAX_PLANES)
250 Com_Error (ERR_DROP, "CM_Q2BSP_LoadPlanes: Map has too many planes");
251 cm_q2_planes = Mem_PoolAlloc (sizeof(cBspPlane_t) * (cm_q2_numPlanes+12), com_cmodelSysPool, 0);
252
253 // Byte swap
254 out = cm_q2_planes;
255 for (i=0 ; i<cm_q2_numPlanes ; i++, in++, out++) {
256 bits = 0;
257 for (j=0 ; j<3 ; j++) {
258 out->normal[j] = LittleFloat (in->normal[j]);
259 if (out->normal[j] < 0)
260 bits |= 1<<j;
261 }
262
263 out->dist = LittleFloat (in->dist);
264 out->type = LittleLong (in->type);
265 out->signBits = bits;
266 }
267 }
268
269
270 /*
271 =================
272 CM_Q2BSP_LoadBrushes
273 =================
274 */
CM_Q2BSP_LoadBrushes(dQ2BspLump_t * l)275 static void CM_Q2BSP_LoadBrushes (dQ2BspLump_t *l)
276 {
277 dQ2BspBrush_t *in;
278 cQ2BspBrush_t *out;
279 int i;
280
281 // Sanity check lump size
282 in = (void *)(cm_q2_mapBuffer + l->fileOfs);
283 if (l->fileLen % sizeof (*in))
284 Com_Error (ERR_DROP, "CM_Q2BSP_LoadBrushes: funny lump size");
285
286 // Find the size and allocate (with extra for box hull)
287 cm_q2_numBrushes = l->fileLen / sizeof (*in);
288 if (cm_q2_numBrushes > Q2BSP_MAX_BRUSHES)
289 Com_Error (ERR_DROP, "CM_Q2BSP_LoadBrushes: Map has too many brushes");
290 cm_q2_brushes = Mem_PoolAlloc (sizeof(cQ2BspBrush_t) * (cm_q2_numBrushes+1), com_cmodelSysPool, 0);
291
292 // Byte swap
293 out = cm_q2_brushes;
294 for (i=0 ; i<cm_q2_numBrushes ; i++, out++, in++) {
295 out->firstBrushSide = LittleLong (in->firstSide);
296 out->numSides = LittleLong (in->numSides);
297 out->contents = LittleLong (in->contents);
298 }
299 }
300
301
302 /*
303 =================
304 CM_Q2BSP_LoadBrushSides
305 =================
306 */
CM_Q2BSP_LoadBrushSides(dQ2BspLump_t * l)307 static void CM_Q2BSP_LoadBrushSides (dQ2BspLump_t *l)
308 {
309 int i, j;
310 cQ2BspBrushSide_t *out;
311 dQ2BspBrushSide_t *in;
312 int num;
313
314 // Sanity check lump size
315 in = (void *)(cm_q2_mapBuffer + l->fileOfs);
316 if (l->fileLen % sizeof (*in))
317 Com_Error (ERR_DROP, "CM_Q2BSP_LoadBrushSides: funny lump size");
318
319 // Find the size and allocate (with extra for box hull)
320 cm_q2_numBrushSides = l->fileLen / sizeof (*in);
321 if (cm_q2_numBrushSides > Q2BSP_MAX_BRUSHSIDES)
322 Com_Error (ERR_DROP, "CM_Q2BSP_LoadBrushSides: Map has too many planes");
323 cm_q2_brushSides = Mem_PoolAlloc (sizeof(cQ2BspBrushSide_t) * (cm_q2_numBrushSides+6), com_cmodelSysPool, 0);
324
325 // Byte swap
326 out = cm_q2_brushSides;
327 for (i=0 ; i<cm_q2_numBrushSides ; i++, in++, out++) {
328 num = LittleShort (in->planeNum);
329 out->plane = &cm_q2_planes[num];
330 j = LittleShort (in->texInfo);
331 if (j >= cm_q2_numTexInfo)
332 Com_Error (ERR_DROP, "CM_Q2BSP_LoadBrushSides: Bad brushside texInfo");
333 out->surface = &cm_q2_surfaces[j];
334 }
335 }
336
337
338 /*
339 =================
340 CM_Q2BSP_LoadSubmodels
341 =================
342 */
CM_Q2BSP_LoadSubmodels(dQ2BspLump_t * l)343 static void CM_Q2BSP_LoadSubmodels (dQ2BspLump_t *l)
344 {
345 dQ2BspModel_t *in;
346 cBspModel_t *out;
347 int i;
348
349 // Sanity check lump size
350 in = (void *)(cm_q2_mapBuffer + l->fileOfs);
351 if (l->fileLen % sizeof (*in))
352 Com_Error (ERR_DROP, "CM_Q2BSP_LoadSubmodels: funny lump size");
353
354 // Find the size
355 cm_numCModels = l->fileLen / sizeof (*in);
356 if (cm_numCModels < 1)
357 Com_Error (ERR_DROP, "CM_Q2BSP_LoadSubmodels: Map with no models");
358 if (cm_numCModels > Q2BSP_MAX_MODELS)
359 Com_Error (ERR_DROP, "CM_Q2BSP_LoadSubmodels: Map has too many models");
360
361 // Byte swap
362 for (i=0 ; i<cm_numCModels ; i++, in++, out++) {
363 out = &cm_mapCModels[i];
364
365 // Spread the mins / maxs by a pixel
366 out->mins[0] = LittleFloat (in->mins[0]) - 1;
367 out->mins[1] = LittleFloat (in->mins[1]) - 1;
368 out->mins[2] = LittleFloat (in->mins[2]) - 1;
369 out->maxs[0] = LittleFloat (in->maxs[0]) + 1;
370 out->maxs[1] = LittleFloat (in->maxs[1]) + 1;
371 out->maxs[2] = LittleFloat (in->maxs[2]) + 1;
372
373 // Head node
374 out->headNode = LittleLong (in->headNode);
375 }
376 }
377
378
379 /*
380 =================
381 CM_Q2BSP_LoadNodes
382 =================
383 */
CM_Q2BSP_LoadNodes(dQ2BspLump_t * l)384 static void CM_Q2BSP_LoadNodes (dQ2BspLump_t *l)
385 {
386 dQ2BspNode_t *in;
387 cQ2BspNode_t *out;
388 int i;
389
390 // Sanity check lump size
391 in = (void *)(cm_q2_mapBuffer + l->fileOfs);
392 if (l->fileLen % sizeof (*in))
393 Com_Error (ERR_DROP, "CM_Q2BSP_LoadNodes: funny lump size");
394
395 // Find the size and allocate (with extra for box hull)
396 cm_q2_numNodes = l->fileLen / sizeof (*in);
397 if (cm_q2_numNodes < 1)
398 Com_Error (ERR_DROP, "CM_Q2BSP_LoadNodes: Map has no nodes");
399 if (cm_q2_numNodes > Q2BSP_MAX_NODES)
400 Com_Error (ERR_DROP, "CM_Q2BSP_LoadNodes: Map has too many nodes");
401 cm_q2_nodes = Mem_PoolAlloc (sizeof(cQ2BspNode_t) * (cm_q2_numNodes+6), com_cmodelSysPool, 0);
402
403 // Byte swap
404 out = cm_q2_nodes;
405 for (i=0 ; i<cm_q2_numNodes ; i++, out++, in++) {
406 out->plane = cm_q2_planes + LittleLong (in->planeNum);
407 out->children[0] = LittleLong (in->children[0]);
408 out->children[1] = LittleLong (in->children[1]);
409 }
410 }
411
412
413 /*
414 =================
415 CM_Q2BSP_LoadAreas
416 =================
417 */
CM_Q2BSP_LoadAreas(dQ2BspLump_t * l)418 static void CM_Q2BSP_LoadAreas (dQ2BspLump_t *l)
419 {
420 int i;
421 cQ2BspArea_t *out;
422 dQ2BspArea_t *in;
423
424 // Sanity check lump size
425 in = (void *)(cm_q2_mapBuffer + l->fileOfs);
426 if (l->fileLen % sizeof (*in))
427 Com_Error (ERR_DROP, "CM_Q2BSP_LoadAreas: funny lump size");
428
429 // Find the size and allocate
430 cm_q2_numAreas = l->fileLen / sizeof (*in);
431 if (cm_q2_numAreas > Q2BSP_MAX_AREAS)
432 Com_Error (ERR_DROP, "CM_Q2BSP_LoadAreas: Map has too many areas");
433 cm_q2_areas = Mem_PoolAlloc (sizeof(cQ2BspArea_t) * cm_q2_numAreas, com_cmodelSysPool, 0);
434
435 // Byte swap
436 out = cm_q2_areas;
437 for (i=0 ; i<cm_q2_numAreas ; i++, in++, out++) {
438 out->numAreaPortals = LittleLong (in->numAreaPortals);
439 out->firstAreaPortal = LittleLong (in->firstAreaPortal);
440 out->floodValid = 0;
441 out->floodNum = 0;
442 }
443 }
444
445
446 /*
447 =================
448 CM_Q2BSP_LoadAreaPortals
449 =================
450 */
CM_Q2BSP_LoadAreaPortals(dQ2BspLump_t * l)451 static void CM_Q2BSP_LoadAreaPortals (dQ2BspLump_t *l)
452 {
453 int i;
454 dQ2BspAreaPortal_t *out;
455 dQ2BspAreaPortal_t *in;
456
457 // Sanity check lump size
458 in = (void *)(cm_q2_mapBuffer + l->fileOfs);
459 if (l->fileLen % sizeof (*in))
460 Com_Error (ERR_DROP, "CM_Q2BSP_LoadAreaPortals: funny lump size");
461
462 // Find the size and allocate
463 cm_q2_numAreaPortals = l->fileLen / sizeof (*in);
464 if (cm_q2_numAreaPortals > Q2BSP_MAX_AREAS)
465 Com_Error (ERR_DROP, "CM_Q2BSP_LoadAreaPortals: Map has too many areas");
466 cm_q2_areaPortals = Mem_PoolAlloc (sizeof(dQ2BspAreaPortal_t) * cm_q2_numAreaPortals, com_cmodelSysPool, 0);
467
468 // Byte swap
469 out = cm_q2_areaPortals;
470 for (i=0 ; i<cm_q2_numAreaPortals ; i++, in++, out++) {
471 out->portalNum = LittleLong (in->portalNum);
472 out->otherArea = LittleLong (in->otherArea);
473 }
474 }
475
476
477 /*
478 =================
479 CM_Q2BSP_LoadVisibility
480 =================
481 */
CM_Q2BSP_LoadVisibility(dQ2BspLump_t * l)482 static void CM_Q2BSP_LoadVisibility (dQ2BspLump_t *l)
483 {
484 int i;
485
486 // Find the size and allocate
487 cm_q2_numVisibility = l->fileLen;
488 if (l->fileLen > Q2BSP_MAX_VISIBILITY)
489 Com_Error (ERR_DROP, "CM_Q2BSP_LoadVisibility: Map has too large visibility lump");
490
491 // If there's no visibility, just store the number of clusters
492 if (!cm_q2_numVisibility) {
493 cm_q2_visData = Mem_PoolAlloc (sizeof(int), com_cmodelSysPool, 0);
494 cm_q2_visData->numClusters = 0;
495 return;
496 }
497
498 // Byte swap
499 cm_q2_visData = Mem_PoolAlloc (sizeof(int) + (sizeof(byte) * cm_q2_numVisibility), com_cmodelSysPool, 0);
500 memcpy (cm_q2_visData, cm_q2_mapBuffer + l->fileOfs, l->fileLen);
501 cm_q2_visData->numClusters = LittleLong (cm_q2_visData->numClusters);
502 for (i=0 ; i<cm_q2_visData->numClusters ; i++) {
503 cm_q2_visData->bitOfs[i][0] = LittleLong (cm_q2_visData->bitOfs[i][0]);
504 cm_q2_visData->bitOfs[i][1] = LittleLong (cm_q2_visData->bitOfs[i][1]);
505 }
506 }
507
508
509 /*
510 =================
511 CM_Q2BSP_LoadEntityString
512 =================
513 */
CM_Q2BSP_LoadEntityString(dQ2BspLump_t * l)514 static void CM_Q2BSP_LoadEntityString (dQ2BspLump_t *l)
515 {
516 // Find the size and allocate (with extra for NULL termination)
517 cm_q2_numEntityChars = l->fileLen;
518 if (l->fileLen > Q2BSP_MAX_ENTSTRING)
519 Com_Error (ERR_DROP, "CM_Q2BSP_LoadEntityString: Map has too large entity lump");
520 cm_q2_entityString = Mem_PoolAlloc (sizeof(char) * (cm_q2_numEntityChars+1), com_cmodelSysPool, 0);
521
522 // Copy data
523 memcpy (cm_q2_entityString, cm_q2_mapBuffer + l->fileOfs, l->fileLen);
524 }
525
526 // ==========================================================================
527
528 /*
529 ==================
530 CM_Q2BSP_LoadMap
531
532 Loads in the map and all submodels
533 ==================
534 */
CM_Q2BSP_LoadMap(uint32 * buffer)535 cBspModel_t *CM_Q2BSP_LoadMap (uint32 *buffer)
536 {
537 dQ2BspHeader_t header;
538 int i;
539
540 //
541 // Allocate space
542 //
543 cm_q2_portalOpen = Mem_PoolAlloc (sizeof(qBool) * Q2BSP_MAX_AREAPORTALS, com_cmodelSysPool, 0);
544
545 //
546 // Byte swap
547 //
548 header = *(dQ2BspHeader_t *)buffer;
549 for (i=0 ; i<sizeof (dQ2BspHeader_t)/4 ; i++)
550 ((int *)&header)[i] = LittleLong (((int *)&header)[i]);
551 cm_q2_mapBuffer = (byte *)buffer;
552
553 //
554 // Load into heap
555 //
556 CM_Q2BSP_LoadSurfaces (&header.lumps[Q2BSP_LUMP_TEXINFO]);
557 CM_Q2BSP_LoadLeafs (&header.lumps[Q2BSP_LUMP_LEAFS]);
558 CM_Q2BSP_LoadLeafBrushes (&header.lumps[Q2BSP_LUMP_LEAFBRUSHES]);
559 CM_Q2BSP_LoadPlanes (&header.lumps[Q2BSP_LUMP_PLANES]);
560 CM_Q2BSP_LoadBrushes (&header.lumps[Q2BSP_LUMP_BRUSHES]);
561 CM_Q2BSP_LoadBrushSides (&header.lumps[Q2BSP_LUMP_BRUSHSIDES]);
562 CM_Q2BSP_LoadSubmodels (&header.lumps[Q2BSP_LUMP_MODELS]);
563 CM_Q2BSP_LoadNodes (&header.lumps[Q2BSP_LUMP_NODES]);
564 CM_Q2BSP_LoadAreas (&header.lumps[Q2BSP_LUMP_AREAS]);
565 CM_Q2BSP_LoadAreaPortals (&header.lumps[Q2BSP_LUMP_AREAPORTALS]);
566 CM_Q2BSP_LoadVisibility (&header.lumps[Q2BSP_LUMP_VISIBILITY]);
567 CM_Q2BSP_LoadEntityString (&header.lumps[Q2BSP_LUMP_ENTITIES]);
568
569 CM_Q2BSP_InitBoxHull ();
570 CM_Q2BSP_PrepMap ();
571
572 return &cm_mapCModels[0];
573 }
574
575
576 /*
577 ==================
578 CM_Q2BSP_PrepMap
579 ==================
580 */
CM_Q2BSP_PrepMap(void)581 void CM_Q2BSP_PrepMap (void)
582 {
583 if (!cm_q2_portalOpen)
584 return;
585
586 memset (cm_q2_portalOpen, 0, sizeof(qBool) * Q2BSP_MAX_AREAPORTALS);
587 CM_Q2BSP_FloodAreaConnections ();
588 }
589
590
591 /*
592 ==================
593 CM_Q2BSP_UnloadMap
594 ==================
595 */
CM_Q2BSP_UnloadMap(void)596 void CM_Q2BSP_UnloadMap (void)
597 {
598 cm_q2_areaPortals = NULL;
599 cm_q2_areas = NULL;
600 cm_q2_brushes = NULL;
601 cm_q2_brushSides = NULL;
602 cm_q2_entityString = cm_q2_emptyEntityString;
603 cm_q2_leafBrushes = NULL;
604 cm_q2_leafs = NULL;
605 cm_q2_nodes = NULL;
606 cm_q2_planes = NULL;
607 cm_q2_portalOpen = NULL;
608 cm_q2_surfaces = NULL;
609 cm_q2_surfacesUnique = NULL;
610 cm_q2_visData = NULL;
611
612 cm_q2_numAreaPortals = 0;
613 cm_q2_numAreas = 1;
614 cm_q2_numBrushes = 0;
615 cm_q2_numBrushSides = 0;
616 cm_q2_numClusters = 1;
617 cm_q2_numEntityChars = 0;
618 cm_q2_numLeafBrushes = 0;
619 cm_q2_numLeafs = 1;
620 cm_q2_numNodes = 0;
621 cm_q2_numPlanes = 0;
622 cm_q2_numTexInfo = 0;
623 cm_q2_numTexInfoUnique = 0;
624 cm_q2_numVisibility = 0;
625 }
626
627 /*
628 =============================================================================
629
630 QUAKE2 BSP INFORMATION
631
632 =============================================================================
633 */
634
635 /*
636 ==================
637 CM_Q2BSP_EntityString
638 ==================
639 */
CM_Q2BSP_EntityString(void)640 char *CM_Q2BSP_EntityString (void)
641 {
642 return cm_q2_entityString;
643 }
644
645
646 /*
647 ==================
648 CM_Q2BSP_SurfRName
649 ==================
650 */
CM_Q2BSP_SurfRName(int texNum)651 char *CM_Q2BSP_SurfRName (int texNum)
652 {
653 return cm_q2_surfacesUnique ? cm_q2_surfacesUnique[texNum]->rname : NULL;
654 }
655
656
657 /*
658 ==================
659 CM_Q2BSP_NumClusters
660 ==================
661 */
CM_Q2BSP_NumClusters(void)662 int CM_Q2BSP_NumClusters (void)
663 {
664 return cm_q2_numClusters;
665 }
666
667
668 /*
669 ==================
670 CM_Q2BSP_NumTexInfo
671 ==================
672 */
CM_Q2BSP_NumTexInfo(void)673 int CM_Q2BSP_NumTexInfo (void)
674 {
675 return cm_q2_numTexInfoUnique;
676 }
677