l_bsp_q3.c (25771B)
1 /* 2 =========================================================================== 3 Copyright (C) 1999-2005 Id Software, Inc. 4 5 This file is part of Quake III Arena source code. 6 7 Quake III Arena source code is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 2 of the License, 10 or (at your option) any later version. 11 12 Quake III Arena source code is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Foobar; if not, write to the Free Software 19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 =========================================================================== 21 */ 22 23 #include "l_cmd.h" 24 #include "l_math.h" 25 #include "l_mem.h" 26 #include "l_log.h" 27 #include "l_poly.h" 28 #include "../botlib/l_script.h" 29 #include "l_qfiles.h" 30 #include "l_bsp_q3.h" 31 #include "l_bsp_ent.h" 32 33 void Q3_ParseEntities (void); 34 void Q3_PrintBSPFileSizes(void); 35 36 void GetLeafNums (void); 37 38 //============================================================================= 39 40 #define WCONVEX_EPSILON 0.5 41 42 43 int q3_nummodels; 44 q3_dmodel_t *q3_dmodels;//[MAX_MAP_MODELS]; 45 46 int q3_numShaders; 47 q3_dshader_t *q3_dshaders;//[Q3_MAX_MAP_SHADERS]; 48 49 int q3_entdatasize; 50 char *q3_dentdata;//[Q3_MAX_MAP_ENTSTRING]; 51 52 int q3_numleafs; 53 q3_dleaf_t *q3_dleafs;//[Q3_MAX_MAP_LEAFS]; 54 55 int q3_numplanes; 56 q3_dplane_t *q3_dplanes;//[Q3_MAX_MAP_PLANES]; 57 58 int q3_numnodes; 59 q3_dnode_t *q3_dnodes;//[Q3_MAX_MAP_NODES]; 60 61 int q3_numleafsurfaces; 62 int *q3_dleafsurfaces;//[Q3_MAX_MAP_LEAFFACES]; 63 64 int q3_numleafbrushes; 65 int *q3_dleafbrushes;//[Q3_MAX_MAP_LEAFBRUSHES]; 66 67 int q3_numbrushes; 68 q3_dbrush_t *q3_dbrushes;//[Q3_MAX_MAP_BRUSHES]; 69 70 int q3_numbrushsides; 71 q3_dbrushside_t *q3_dbrushsides;//[Q3_MAX_MAP_BRUSHSIDES]; 72 73 int q3_numLightBytes; 74 byte *q3_lightBytes;//[Q3_MAX_MAP_LIGHTING]; 75 76 int q3_numGridPoints; 77 byte *q3_gridData;//[Q3_MAX_MAP_LIGHTGRID]; 78 79 int q3_numVisBytes; 80 byte *q3_visBytes;//[Q3_MAX_MAP_VISIBILITY]; 81 82 int q3_numDrawVerts; 83 q3_drawVert_t *q3_drawVerts;//[Q3_MAX_MAP_DRAW_VERTS]; 84 85 int q3_numDrawIndexes; 86 int *q3_drawIndexes;//[Q3_MAX_MAP_DRAW_INDEXES]; 87 88 int q3_numDrawSurfaces; 89 q3_dsurface_t *q3_drawSurfaces;//[Q3_MAX_MAP_DRAW_SURFS]; 90 91 int q3_numFogs; 92 q3_dfog_t *q3_dfogs;//[Q3_MAX_MAP_FOGS]; 93 94 char q3_dbrushsidetextured[Q3_MAX_MAP_BRUSHSIDES]; 95 96 extern qboolean forcesidesvisible; 97 98 //=========================================================================== 99 // 100 // Parameter: - 101 // Returns: - 102 // Changes Globals: - 103 //=========================================================================== 104 void Q3_FreeMaxBSP(void) 105 { 106 if (q3_dmodels) FreeMemory(q3_dmodels); 107 q3_dmodels = NULL; 108 q3_nummodels = 0; 109 if (q3_dshaders) FreeMemory(q3_dshaders); 110 q3_dshaders = NULL; 111 q3_numShaders = 0; 112 if (q3_dentdata) FreeMemory(q3_dentdata); 113 q3_dentdata = NULL; 114 q3_entdatasize = 0; 115 if (q3_dleafs) FreeMemory(q3_dleafs); 116 q3_dleafs = NULL; 117 q3_numleafs = 0; 118 if (q3_dplanes) FreeMemory(q3_dplanes); 119 q3_dplanes = NULL; 120 q3_numplanes = 0; 121 if (q3_dnodes) FreeMemory(q3_dnodes); 122 q3_dnodes = NULL; 123 q3_numnodes = 0; 124 if (q3_dleafsurfaces) FreeMemory(q3_dleafsurfaces); 125 q3_dleafsurfaces = NULL; 126 q3_numleafsurfaces = 0; 127 if (q3_dleafbrushes) FreeMemory(q3_dleafbrushes); 128 q3_dleafbrushes = NULL; 129 q3_numleafbrushes = 0; 130 if (q3_dbrushes) FreeMemory(q3_dbrushes); 131 q3_dbrushes = NULL; 132 q3_numbrushes = 0; 133 if (q3_dbrushsides) FreeMemory(q3_dbrushsides); 134 q3_dbrushsides = NULL; 135 q3_numbrushsides = 0; 136 if (q3_lightBytes) FreeMemory(q3_lightBytes); 137 q3_lightBytes = NULL; 138 q3_numLightBytes = 0; 139 if (q3_gridData) FreeMemory(q3_gridData); 140 q3_gridData = NULL; 141 q3_numGridPoints = 0; 142 if (q3_visBytes) FreeMemory(q3_visBytes); 143 q3_visBytes = NULL; 144 q3_numVisBytes = 0; 145 if (q3_drawVerts) FreeMemory(q3_drawVerts); 146 q3_drawVerts = NULL; 147 q3_numDrawVerts = 0; 148 if (q3_drawIndexes) FreeMemory(q3_drawIndexes); 149 q3_drawIndexes = NULL; 150 q3_numDrawIndexes = 0; 151 if (q3_drawSurfaces) FreeMemory(q3_drawSurfaces); 152 q3_drawSurfaces = NULL; 153 q3_numDrawSurfaces = 0; 154 if (q3_dfogs) FreeMemory(q3_dfogs); 155 q3_dfogs = NULL; 156 q3_numFogs = 0; 157 } //end of the function Q3_FreeMaxBSP 158 159 160 //=========================================================================== 161 // 162 // Parameter: - 163 // Returns: - 164 // Changes Globals: - 165 //=========================================================================== 166 void Q3_PlaneFromPoints(vec3_t p0, vec3_t p1, vec3_t p2, vec3_t normal, float *dist) 167 { 168 vec3_t t1, t2; 169 170 VectorSubtract(p0, p1, t1); 171 VectorSubtract(p2, p1, t2); 172 CrossProduct(t1, t2, normal); 173 VectorNormalize(normal); 174 175 *dist = DotProduct(p0, normal); 176 } //end of the function PlaneFromPoints 177 //=========================================================================== 178 // 179 // Parameter: - 180 // Returns: - 181 // Changes Globals: - 182 //=========================================================================== 183 void Q3_SurfacePlane(q3_dsurface_t *surface, vec3_t normal, float *dist) 184 { 185 int i; 186 float *p0, *p1, *p2; 187 vec3_t t1, t2; 188 189 p0 = q3_drawVerts[surface->firstVert].xyz; 190 for (i = 1; i < surface->numVerts-1; i++) 191 { 192 p1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz; 193 p2 = q3_drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz; 194 VectorSubtract(p0, p1, t1); 195 VectorSubtract(p2, p1, t2); 196 CrossProduct(t1, t2, normal); 197 VectorNormalize(normal); 198 if (VectorLength(normal)) break; 199 } //end for*/ 200 /* 201 float dot; 202 for (i = 0; i < surface->numVerts; i++) 203 { 204 p0 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz; 205 p1 = q3_drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz; 206 p2 = q3_drawVerts[surface->firstVert + ((i+2) % surface->numVerts)].xyz; 207 VectorSubtract(p0, p1, t1); 208 VectorSubtract(p2, p1, t2); 209 VectorNormalize(t1); 210 VectorNormalize(t2); 211 dot = DotProduct(t1, t2); 212 if (dot > -0.9 && dot < 0.9 && 213 VectorLength(t1) > 0.1 && VectorLength(t2) > 0.1) break; 214 } //end for 215 CrossProduct(t1, t2, normal); 216 VectorNormalize(normal); 217 */ 218 if (VectorLength(normal) < 0.9) 219 { 220 printf("surface %d bogus normal vector %f %f %f\n", surface - q3_drawSurfaces, normal[0], normal[1], normal[2]); 221 printf("t1 = %f %f %f, t2 = %f %f %f\n", t1[0], t1[1], t1[2], t2[0], t2[1], t2[2]); 222 for (i = 0; i < surface->numVerts; i++) 223 { 224 p1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz; 225 Log_Print("p%d = %f %f %f\n", i, p1[0], p1[1], p1[2]); 226 } //end for 227 } //end if 228 *dist = DotProduct(p0, normal); 229 } //end of the function Q3_SurfacePlane 230 //=========================================================================== 231 // 232 // Parameter: - 233 // Returns: - 234 // Changes Globals: - 235 //=========================================================================== 236 q3_dplane_t *q3_surfaceplanes; 237 238 void Q3_CreatePlanarSurfacePlanes(void) 239 { 240 int i; 241 q3_dsurface_t *surface; 242 243 Log_Print("creating planar surface planes...\n"); 244 q3_surfaceplanes = (q3_dplane_t *) GetClearedMemory(q3_numDrawSurfaces * sizeof(q3_dplane_t)); 245 246 for (i = 0; i < q3_numDrawSurfaces; i++) 247 { 248 surface = &q3_drawSurfaces[i]; 249 if (surface->surfaceType != MST_PLANAR) continue; 250 Q3_SurfacePlane(surface, q3_surfaceplanes[i].normal, &q3_surfaceplanes[i].dist); 251 //Log_Print("normal = %f %f %f, dist = %f\n", q3_surfaceplanes[i].normal[0], 252 // q3_surfaceplanes[i].normal[1], 253 // q3_surfaceplanes[i].normal[2], q3_surfaceplanes[i].dist); 254 } //end for 255 } //end of the function Q3_CreatePlanarSurfacePlanes 256 //=========================================================================== 257 // 258 // Parameter: - 259 // Returns: - 260 // Changes Globals: - 261 //=========================================================================== 262 /* 263 void Q3_SurfacePlane(q3_dsurface_t *surface, vec3_t normal, float *dist) 264 { 265 //take the plane information from the lightmap vector 266 //VectorCopy(surface->lightmapVecs[2], normal); 267 //calculate plane dist with first surface vertex 268 //*dist = DotProduct(q3_drawVerts[surface->firstVert].xyz, normal); 269 Q3_PlaneFromPoints(q3_drawVerts[surface->firstVert].xyz, 270 q3_drawVerts[surface->firstVert+1].xyz, 271 q3_drawVerts[surface->firstVert+2].xyz, normal, dist); 272 } //end of the function Q3_SurfacePlane*/ 273 //=========================================================================== 274 // returns the amount the face and the winding overlap 275 // 276 // Parameter: - 277 // Returns: - 278 // Changes Globals: - 279 //=========================================================================== 280 float Q3_FaceOnWinding(q3_dsurface_t *surface, winding_t *winding) 281 { 282 int i; 283 float dist, area; 284 q3_dplane_t plane; 285 vec_t *v1, *v2; 286 vec3_t normal, edgevec; 287 winding_t *w; 288 289 //copy the winding before chopping 290 w = CopyWinding(winding); 291 //retrieve the surface plane 292 Q3_SurfacePlane(surface, plane.normal, &plane.dist); 293 //chop the winding with the surface edge planes 294 for (i = 0; i < surface->numVerts && w; i++) 295 { 296 v1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz; 297 v2 = q3_drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz; 298 //create a plane through the edge from v1 to v2, orthogonal to the 299 //surface plane and with the normal vector pointing inward 300 VectorSubtract(v2, v1, edgevec); 301 CrossProduct(edgevec, plane.normal, normal); 302 VectorNormalize(normal); 303 dist = DotProduct(normal, v1); 304 // 305 ChopWindingInPlace(&w, normal, dist, -0.1); //CLIP_EPSILON 306 } //end for 307 if (w) 308 { 309 area = WindingArea(w); 310 FreeWinding(w); 311 return area; 312 } //end if 313 return 0; 314 } //end of the function Q3_FaceOnWinding 315 //=========================================================================== 316 // creates a winding for the given brush side on the given brush 317 // 318 // Parameter: - 319 // Returns: - 320 // Changes Globals: - 321 //=========================================================================== 322 winding_t *Q3_BrushSideWinding(q3_dbrush_t *brush, q3_dbrushside_t *baseside) 323 { 324 int i; 325 q3_dplane_t *baseplane, *plane; 326 winding_t *w; 327 q3_dbrushside_t *side; 328 329 //create a winding for the brush side with the given planenumber 330 baseplane = &q3_dplanes[baseside->planeNum]; 331 w = BaseWindingForPlane(baseplane->normal, baseplane->dist); 332 for (i = 0; i < brush->numSides && w; i++) 333 { 334 side = &q3_dbrushsides[brush->firstSide + i]; 335 //don't chop with the base plane 336 if (side->planeNum == baseside->planeNum) continue; 337 //also don't use planes that are almost equal 338 plane = &q3_dplanes[side->planeNum]; 339 if (DotProduct(baseplane->normal, plane->normal) > 0.999 340 && fabs(baseplane->dist - plane->dist) < 0.01) continue; 341 // 342 plane = &q3_dplanes[side->planeNum^1]; 343 ChopWindingInPlace(&w, plane->normal, plane->dist, -0.1); //CLIP_EPSILON); 344 } //end for 345 return w; 346 } //end of the function Q3_BrushSideWinding 347 //=========================================================================== 348 // fix screwed brush texture references 349 // 350 // Parameter: - 351 // Returns: - 352 // Changes Globals: - 353 //=========================================================================== 354 qboolean WindingIsTiny(winding_t *w); 355 356 void Q3_FindVisibleBrushSides(void) 357 { 358 int i, j, k, we, numtextured, numsides; 359 float dot; 360 q3_dplane_t *plane; 361 q3_dbrushside_t *brushside; 362 q3_dbrush_t *brush; 363 q3_dsurface_t *surface; 364 winding_t *w; 365 366 memset(q3_dbrushsidetextured, false, Q3_MAX_MAP_BRUSHSIDES); 367 // 368 numsides = 0; 369 //create planes for the planar surfaces 370 Q3_CreatePlanarSurfacePlanes(); 371 Log_Print("searching visible brush sides...\n"); 372 Log_Print("%6d brush sides", numsides); 373 //go over all the brushes 374 for (i = 0; i < q3_numbrushes; i++) 375 { 376 brush = &q3_dbrushes[i]; 377 //go over all the sides of the brush 378 for (j = 0; j < brush->numSides; j++) 379 { 380 qprintf("\r%6d", numsides++); 381 brushside = &q3_dbrushsides[brush->firstSide + j]; 382 // 383 w = Q3_BrushSideWinding(brush, brushside); 384 if (!w) 385 { 386 q3_dbrushsidetextured[brush->firstSide + j] = true; 387 continue; 388 } //end if 389 else 390 { 391 //RemoveEqualPoints(w, 0.2); 392 if (WindingIsTiny(w)) 393 { 394 FreeWinding(w); 395 q3_dbrushsidetextured[brush->firstSide + j] = true; 396 continue; 397 } //end if 398 else 399 { 400 we = WindingError(w); 401 if (we == WE_NOTENOUGHPOINTS 402 || we == WE_SMALLAREA 403 || we == WE_POINTBOGUSRANGE 404 // || we == WE_NONCONVEX 405 ) 406 { 407 FreeWinding(w); 408 q3_dbrushsidetextured[brush->firstSide + j] = true; 409 continue; 410 } //end if 411 } //end else 412 } //end else 413 if (WindingArea(w) < 20) 414 { 415 q3_dbrushsidetextured[brush->firstSide + j] = true; 416 continue; 417 } //end if 418 //find a face for texturing this brush 419 for (k = 0; k < q3_numDrawSurfaces; k++) 420 { 421 surface = &q3_drawSurfaces[k]; 422 if (surface->surfaceType != MST_PLANAR) continue; 423 // 424 //Q3_SurfacePlane(surface, plane.normal, &plane.dist); 425 plane = &q3_surfaceplanes[k]; 426 //the surface plane and the brush side plane should be pretty much the same 427 if (fabs(fabs(plane->dist) - fabs(q3_dplanes[brushside->planeNum].dist)) > 5) continue; 428 dot = DotProduct(plane->normal, q3_dplanes[brushside->planeNum].normal); 429 if (dot > -0.9 && dot < 0.9) continue; 430 //if the face is partly or totally on the brush side 431 if (Q3_FaceOnWinding(surface, w)) 432 { 433 q3_dbrushsidetextured[brush->firstSide + j] = true; 434 //Log_Write("Q3_FaceOnWinding"); 435 break; 436 } //end if 437 } //end for 438 FreeWinding(w); 439 } //end for 440 } //end for 441 qprintf("\r%6d brush sides\n", numsides); 442 numtextured = 0; 443 for (i = 0; i < q3_numbrushsides; i++) 444 { 445 if (forcesidesvisible) q3_dbrushsidetextured[i] = true; 446 if (q3_dbrushsidetextured[i]) numtextured++; 447 } //end for 448 Log_Print("%d brush sides textured out of %d\n", numtextured, q3_numbrushsides); 449 } //end of the function Q3_FindVisibleBrushSides 450 451 /* 452 ============= 453 Q3_SwapBlock 454 455 If all values are 32 bits, this can be used to swap everything 456 ============= 457 */ 458 void Q3_SwapBlock( int *block, int sizeOfBlock ) { 459 int i; 460 461 sizeOfBlock >>= 2; 462 for ( i = 0 ; i < sizeOfBlock ; i++ ) { 463 block[i] = LittleLong( block[i] ); 464 } 465 } //end of the function Q3_SwapBlock 466 467 /* 468 ============= 469 Q3_SwapBSPFile 470 471 Byte swaps all data in a bsp file. 472 ============= 473 */ 474 void Q3_SwapBSPFile( void ) { 475 int i; 476 477 // models 478 Q3_SwapBlock( (int *)q3_dmodels, q3_nummodels * sizeof( q3_dmodels[0] ) ); 479 480 // shaders (don't swap the name) 481 for ( i = 0 ; i < q3_numShaders ; i++ ) { 482 q3_dshaders[i].contentFlags = LittleLong( q3_dshaders[i].contentFlags ); 483 q3_dshaders[i].surfaceFlags = LittleLong( q3_dshaders[i].surfaceFlags ); 484 } 485 486 // planes 487 Q3_SwapBlock( (int *)q3_dplanes, q3_numplanes * sizeof( q3_dplanes[0] ) ); 488 489 // nodes 490 Q3_SwapBlock( (int *)q3_dnodes, q3_numnodes * sizeof( q3_dnodes[0] ) ); 491 492 // leafs 493 Q3_SwapBlock( (int *)q3_dleafs, q3_numleafs * sizeof( q3_dleafs[0] ) ); 494 495 // leaffaces 496 Q3_SwapBlock( (int *)q3_dleafsurfaces, q3_numleafsurfaces * sizeof( q3_dleafsurfaces[0] ) ); 497 498 // leafbrushes 499 Q3_SwapBlock( (int *)q3_dleafbrushes, q3_numleafbrushes * sizeof( q3_dleafbrushes[0] ) ); 500 501 // brushes 502 Q3_SwapBlock( (int *)q3_dbrushes, q3_numbrushes * sizeof( q3_dbrushes[0] ) ); 503 504 // brushsides 505 Q3_SwapBlock( (int *)q3_dbrushsides, q3_numbrushsides * sizeof( q3_dbrushsides[0] ) ); 506 507 // vis 508 ((int *)&q3_visBytes)[0] = LittleLong( ((int *)&q3_visBytes)[0] ); 509 ((int *)&q3_visBytes)[1] = LittleLong( ((int *)&q3_visBytes)[1] ); 510 511 // drawverts (don't swap colors ) 512 for ( i = 0 ; i < q3_numDrawVerts ; i++ ) { 513 q3_drawVerts[i].lightmap[0] = LittleFloat( q3_drawVerts[i].lightmap[0] ); 514 q3_drawVerts[i].lightmap[1] = LittleFloat( q3_drawVerts[i].lightmap[1] ); 515 q3_drawVerts[i].st[0] = LittleFloat( q3_drawVerts[i].st[0] ); 516 q3_drawVerts[i].st[1] = LittleFloat( q3_drawVerts[i].st[1] ); 517 q3_drawVerts[i].xyz[0] = LittleFloat( q3_drawVerts[i].xyz[0] ); 518 q3_drawVerts[i].xyz[1] = LittleFloat( q3_drawVerts[i].xyz[1] ); 519 q3_drawVerts[i].xyz[2] = LittleFloat( q3_drawVerts[i].xyz[2] ); 520 q3_drawVerts[i].normal[0] = LittleFloat( q3_drawVerts[i].normal[0] ); 521 q3_drawVerts[i].normal[1] = LittleFloat( q3_drawVerts[i].normal[1] ); 522 q3_drawVerts[i].normal[2] = LittleFloat( q3_drawVerts[i].normal[2] ); 523 } 524 525 // drawindexes 526 Q3_SwapBlock( (int *)q3_drawIndexes, q3_numDrawIndexes * sizeof( q3_drawIndexes[0] ) ); 527 528 // drawsurfs 529 Q3_SwapBlock( (int *)q3_drawSurfaces, q3_numDrawSurfaces * sizeof( q3_drawSurfaces[0] ) ); 530 531 // fogs 532 for ( i = 0 ; i < q3_numFogs ; i++ ) { 533 q3_dfogs[i].brushNum = LittleLong( q3_dfogs[i].brushNum ); 534 } 535 } 536 537 538 539 /* 540 ============= 541 Q3_CopyLump 542 ============= 543 */ 544 int Q3_CopyLump( q3_dheader_t *header, int lump, void **dest, int size ) { 545 int length, ofs; 546 547 length = header->lumps[lump].filelen; 548 ofs = header->lumps[lump].fileofs; 549 550 if ( length % size ) { 551 Error ("Q3_LoadBSPFile: odd lump size"); 552 } 553 554 *dest = GetMemory(length); 555 556 memcpy( *dest, (byte *)header + ofs, length ); 557 558 return length / size; 559 } 560 561 /* 562 ============= 563 CountTriangles 564 ============= 565 */ 566 void CountTriangles( void ) { 567 int i, numTris, numPatchTris; 568 q3_dsurface_t *surface; 569 570 numTris = numPatchTris = 0; 571 for ( i = 0; i < q3_numDrawSurfaces; i++ ) { 572 surface = &q3_drawSurfaces[i]; 573 574 numTris += surface->numIndexes / 3; 575 576 if ( surface->patchWidth ) { 577 numPatchTris += surface->patchWidth * surface->patchHeight * 2; 578 } 579 } 580 581 Log_Print( "%6d triangles\n", numTris ); 582 Log_Print( "%6d patch tris\n", numPatchTris ); 583 } 584 585 /* 586 ============= 587 Q3_LoadBSPFile 588 ============= 589 */ 590 void Q3_LoadBSPFile(struct quakefile_s *qf) 591 { 592 q3_dheader_t *header; 593 594 // load the file header 595 //LoadFile(filename, (void **)&header, offset, length); 596 // 597 LoadQuakeFile(qf, (void **)&header); 598 599 // swap the header 600 Q3_SwapBlock( (int *)header, sizeof(*header) ); 601 602 if ( header->ident != Q3_BSP_IDENT ) { 603 Error( "%s is not a IBSP file", qf->filename ); 604 } 605 if ( header->version != Q3_BSP_VERSION ) { 606 Error( "%s is version %i, not %i", qf->filename, header->version, Q3_BSP_VERSION ); 607 } 608 609 q3_numShaders = Q3_CopyLump( header, Q3_LUMP_SHADERS, (void *) &q3_dshaders, sizeof(q3_dshader_t) ); 610 q3_nummodels = Q3_CopyLump( header, Q3_LUMP_MODELS, (void *) &q3_dmodels, sizeof(q3_dmodel_t) ); 611 q3_numplanes = Q3_CopyLump( header, Q3_LUMP_PLANES, (void *) &q3_dplanes, sizeof(q3_dplane_t) ); 612 q3_numleafs = Q3_CopyLump( header, Q3_LUMP_LEAFS, (void *) &q3_dleafs, sizeof(q3_dleaf_t) ); 613 q3_numnodes = Q3_CopyLump( header, Q3_LUMP_NODES, (void *) &q3_dnodes, sizeof(q3_dnode_t) ); 614 q3_numleafsurfaces = Q3_CopyLump( header, Q3_LUMP_LEAFSURFACES, (void *) &q3_dleafsurfaces, sizeof(q3_dleafsurfaces[0]) ); 615 q3_numleafbrushes = Q3_CopyLump( header, Q3_LUMP_LEAFBRUSHES, (void *) &q3_dleafbrushes, sizeof(q3_dleafbrushes[0]) ); 616 q3_numbrushes = Q3_CopyLump( header, Q3_LUMP_BRUSHES, (void *) &q3_dbrushes, sizeof(q3_dbrush_t) ); 617 q3_numbrushsides = Q3_CopyLump( header, Q3_LUMP_BRUSHSIDES, (void *) &q3_dbrushsides, sizeof(q3_dbrushside_t) ); 618 q3_numDrawVerts = Q3_CopyLump( header, Q3_LUMP_DRAWVERTS, (void *) &q3_drawVerts, sizeof(q3_drawVert_t) ); 619 q3_numDrawSurfaces = Q3_CopyLump( header, Q3_LUMP_SURFACES, (void *) &q3_drawSurfaces, sizeof(q3_dsurface_t) ); 620 q3_numFogs = Q3_CopyLump( header, Q3_LUMP_FOGS, (void *) &q3_dfogs, sizeof(q3_dfog_t) ); 621 q3_numDrawIndexes = Q3_CopyLump( header, Q3_LUMP_DRAWINDEXES, (void *) &q3_drawIndexes, sizeof(q3_drawIndexes[0]) ); 622 623 q3_numVisBytes = Q3_CopyLump( header, Q3_LUMP_VISIBILITY, (void *) &q3_visBytes, 1 ); 624 q3_numLightBytes = Q3_CopyLump( header, Q3_LUMP_LIGHTMAPS, (void *) &q3_lightBytes, 1 ); 625 q3_entdatasize = Q3_CopyLump( header, Q3_LUMP_ENTITIES, (void *) &q3_dentdata, 1); 626 627 q3_numGridPoints = Q3_CopyLump( header, Q3_LUMP_LIGHTGRID, (void *) &q3_gridData, 8 ); 628 629 CountTriangles(); 630 631 FreeMemory( header ); // everything has been copied out 632 633 // swap everything 634 Q3_SwapBSPFile(); 635 636 Q3_FindVisibleBrushSides(); 637 638 //Q3_PrintBSPFileSizes(); 639 } 640 641 642 //============================================================================ 643 644 /* 645 ============= 646 Q3_AddLump 647 ============= 648 */ 649 void Q3_AddLump( FILE *bspfile, q3_dheader_t *header, int lumpnum, void *data, int len ) { 650 q3_lump_t *lump; 651 652 lump = &header->lumps[lumpnum]; 653 654 lump->fileofs = LittleLong( ftell(bspfile) ); 655 lump->filelen = LittleLong( len ); 656 SafeWrite( bspfile, data, (len+3)&~3 ); 657 } 658 659 /* 660 ============= 661 Q3_WriteBSPFile 662 663 Swaps the bsp file in place, so it should not be referenced again 664 ============= 665 */ 666 void Q3_WriteBSPFile( char *filename ) 667 { 668 q3_dheader_t outheader, *header; 669 FILE *bspfile; 670 671 header = &outheader; 672 memset( header, 0, sizeof(q3_dheader_t) ); 673 674 Q3_SwapBSPFile(); 675 676 header->ident = LittleLong( Q3_BSP_IDENT ); 677 header->version = LittleLong( Q3_BSP_VERSION ); 678 679 bspfile = SafeOpenWrite( filename ); 680 SafeWrite( bspfile, header, sizeof(q3_dheader_t) ); // overwritten later 681 682 Q3_AddLump( bspfile, header, Q3_LUMP_SHADERS, q3_dshaders, q3_numShaders*sizeof(q3_dshader_t) ); 683 Q3_AddLump( bspfile, header, Q3_LUMP_PLANES, q3_dplanes, q3_numplanes*sizeof(q3_dplane_t) ); 684 Q3_AddLump( bspfile, header, Q3_LUMP_LEAFS, q3_dleafs, q3_numleafs*sizeof(q3_dleaf_t) ); 685 Q3_AddLump( bspfile, header, Q3_LUMP_NODES, q3_dnodes, q3_numnodes*sizeof(q3_dnode_t) ); 686 Q3_AddLump( bspfile, header, Q3_LUMP_BRUSHES, q3_dbrushes, q3_numbrushes*sizeof(q3_dbrush_t) ); 687 Q3_AddLump( bspfile, header, Q3_LUMP_BRUSHSIDES, q3_dbrushsides, q3_numbrushsides*sizeof(q3_dbrushside_t) ); 688 Q3_AddLump( bspfile, header, Q3_LUMP_LEAFSURFACES, q3_dleafsurfaces, q3_numleafsurfaces*sizeof(q3_dleafsurfaces[0]) ); 689 Q3_AddLump( bspfile, header, Q3_LUMP_LEAFBRUSHES, q3_dleafbrushes, q3_numleafbrushes*sizeof(q3_dleafbrushes[0]) ); 690 Q3_AddLump( bspfile, header, Q3_LUMP_MODELS, q3_dmodels, q3_nummodels*sizeof(q3_dmodel_t) ); 691 Q3_AddLump( bspfile, header, Q3_LUMP_DRAWVERTS, q3_drawVerts, q3_numDrawVerts*sizeof(q3_drawVert_t) ); 692 Q3_AddLump( bspfile, header, Q3_LUMP_SURFACES, q3_drawSurfaces, q3_numDrawSurfaces*sizeof(q3_dsurface_t) ); 693 Q3_AddLump( bspfile, header, Q3_LUMP_VISIBILITY, q3_visBytes, q3_numVisBytes ); 694 Q3_AddLump( bspfile, header, Q3_LUMP_LIGHTMAPS, q3_lightBytes, q3_numLightBytes ); 695 Q3_AddLump( bspfile, header, Q3_LUMP_LIGHTGRID, q3_gridData, 8 * q3_numGridPoints ); 696 Q3_AddLump( bspfile, header, Q3_LUMP_ENTITIES, q3_dentdata, q3_entdatasize ); 697 Q3_AddLump( bspfile, header, Q3_LUMP_FOGS, q3_dfogs, q3_numFogs * sizeof(q3_dfog_t) ); 698 Q3_AddLump( bspfile, header, Q3_LUMP_DRAWINDEXES, q3_drawIndexes, q3_numDrawIndexes * sizeof(q3_drawIndexes[0]) ); 699 700 fseek (bspfile, 0, SEEK_SET); 701 SafeWrite (bspfile, header, sizeof(q3_dheader_t)); 702 fclose (bspfile); 703 } 704 705 //============================================================================ 706 707 /* 708 ============= 709 Q3_PrintBSPFileSizes 710 711 Dumps info about current file 712 ============= 713 */ 714 void Q3_PrintBSPFileSizes( void ) 715 { 716 if ( !num_entities ) 717 { 718 Q3_ParseEntities(); 719 } 720 721 Log_Print ("%6i models %7i\n" 722 ,q3_nummodels, (int)(q3_nummodels*sizeof(q3_dmodel_t))); 723 Log_Print ("%6i shaders %7i\n" 724 ,q3_numShaders, (int)(q3_numShaders*sizeof(q3_dshader_t))); 725 Log_Print ("%6i brushes %7i\n" 726 ,q3_numbrushes, (int)(q3_numbrushes*sizeof(q3_dbrush_t))); 727 Log_Print ("%6i brushsides %7i\n" 728 ,q3_numbrushsides, (int)(q3_numbrushsides*sizeof(q3_dbrushside_t))); 729 Log_Print ("%6i fogs %7i\n" 730 ,q3_numFogs, (int)(q3_numFogs*sizeof(q3_dfog_t))); 731 Log_Print ("%6i planes %7i\n" 732 ,q3_numplanes, (int)(q3_numplanes*sizeof(q3_dplane_t))); 733 Log_Print ("%6i entdata %7i\n", num_entities, q3_entdatasize); 734 735 Log_Print ("\n"); 736 737 Log_Print ("%6i nodes %7i\n" 738 ,q3_numnodes, (int)(q3_numnodes*sizeof(q3_dnode_t))); 739 Log_Print ("%6i leafs %7i\n" 740 ,q3_numleafs, (int)(q3_numleafs*sizeof(q3_dleaf_t))); 741 Log_Print ("%6i leafsurfaces %7i\n" 742 ,q3_numleafsurfaces, (int)(q3_numleafsurfaces*sizeof(q3_dleafsurfaces[0]))); 743 Log_Print ("%6i leafbrushes %7i\n" 744 ,q3_numleafbrushes, (int)(q3_numleafbrushes*sizeof(q3_dleafbrushes[0]))); 745 Log_Print ("%6i drawverts %7i\n" 746 ,q3_numDrawVerts, (int)(q3_numDrawVerts*sizeof(q3_drawVerts[0]))); 747 Log_Print ("%6i drawindexes %7i\n" 748 ,q3_numDrawIndexes, (int)(q3_numDrawIndexes*sizeof(q3_drawIndexes[0]))); 749 Log_Print ("%6i drawsurfaces %7i\n" 750 ,q3_numDrawSurfaces, (int)(q3_numDrawSurfaces*sizeof(q3_drawSurfaces[0]))); 751 752 Log_Print ("%6i lightmaps %7i\n" 753 ,q3_numLightBytes / (LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT*3), q3_numLightBytes ); 754 Log_Print (" visibility %7i\n" 755 , q3_numVisBytes ); 756 } 757 758 /* 759 ================ 760 Q3_ParseEntities 761 762 Parses the q3_dentdata string into entities 763 ================ 764 */ 765 void Q3_ParseEntities (void) 766 { 767 script_t *script; 768 769 num_entities = 0; 770 script = LoadScriptMemory(q3_dentdata, q3_entdatasize, "*Quake3 bsp file"); 771 SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES | 772 SCFL_NOSTRINGESCAPECHARS); 773 774 while(ParseEntity(script)) 775 { 776 } //end while 777 778 FreeScript(script); 779 } //end of the function Q3_ParseEntities 780 781 782 /* 783 ================ 784 Q3_UnparseEntities 785 786 Generates the q3_dentdata string from all the entities 787 ================ 788 */ 789 void Q3_UnparseEntities (void) 790 { 791 char *buf, *end; 792 epair_t *ep; 793 char line[2048]; 794 int i; 795 796 buf = q3_dentdata; 797 end = buf; 798 *end = 0; 799 800 for (i=0 ; i<num_entities ; i++) 801 { 802 ep = entities[i].epairs; 803 if (!ep) 804 continue; // ent got removed 805 806 strcat (end,"{\n"); 807 end += 2; 808 809 for (ep = entities[i].epairs ; ep ; ep=ep->next) 810 { 811 sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value); 812 strcat (end, line); 813 end += strlen(line); 814 } 815 strcat (end,"}\n"); 816 end += 2; 817 818 if (end > buf + Q3_MAX_MAP_ENTSTRING) 819 Error ("Entity text too long"); 820 } 821 q3_entdatasize = end - buf + 1; 822 } //end of the function Q3_UnparseEntities 823 824