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