00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "l_cmd.h"
00024 #include "l_math.h"
00025 #include "l_mem.h"
00026 #include "l_log.h"
00027 #include "l_poly.h"
00028 #include "../botlib/l_script.h"
00029 #include "l_qfiles.h"
00030 #include "l_bsp_q3.h"
00031 #include "l_bsp_ent.h"
00032
00033 void Q3_ParseEntities (void);
00034 void Q3_PrintBSPFileSizes(void);
00035
00036 void GetLeafNums (void);
00037
00038
00039
00040 #define WCONVEX_EPSILON 0.5
00041
00042
00043 int q3_nummodels;
00044 q3_dmodel_t *q3_dmodels;
00045
00046 int q3_numShaders;
00047 q3_dshader_t *q3_dshaders;
00048
00049 int q3_entdatasize;
00050 char *q3_dentdata;
00051
00052 int q3_numleafs;
00053 q3_dleaf_t *q3_dleafs;
00054
00055 int q3_numplanes;
00056 q3_dplane_t *q3_dplanes;
00057
00058 int q3_numnodes;
00059 q3_dnode_t *q3_dnodes;
00060
00061 int q3_numleafsurfaces;
00062 int *q3_dleafsurfaces;
00063
00064 int q3_numleafbrushes;
00065 int *q3_dleafbrushes;
00066
00067 int q3_numbrushes;
00068 q3_dbrush_t *q3_dbrushes;
00069
00070 int q3_numbrushsides;
00071 q3_dbrushside_t *q3_dbrushsides;
00072
00073 int q3_numLightBytes;
00074 byte *q3_lightBytes;
00075
00076 int q3_numGridPoints;
00077 byte *q3_gridData;
00078
00079 int q3_numVisBytes;
00080 byte *q3_visBytes;
00081
00082 int q3_numDrawVerts;
00083 q3_drawVert_t *q3_drawVerts;
00084
00085 int q3_numDrawIndexes;
00086 int *q3_drawIndexes;
00087
00088 int q3_numDrawSurfaces;
00089 q3_dsurface_t *q3_drawSurfaces;
00090
00091 int q3_numFogs;
00092 q3_dfog_t *q3_dfogs;
00093
00094 char q3_dbrushsidetextured[Q3_MAX_MAP_BRUSHSIDES];
00095
00096 extern qboolean forcesidesvisible;
00097
00098
00099
00100
00101
00102
00103
00104 void Q3_FreeMaxBSP(void)
00105 {
00106 if (q3_dmodels) FreeMemory(q3_dmodels);
00107 q3_dmodels = NULL;
00108 q3_nummodels = 0;
00109 if (q3_dshaders) FreeMemory(q3_dshaders);
00110 q3_dshaders = NULL;
00111 q3_numShaders = 0;
00112 if (q3_dentdata) FreeMemory(q3_dentdata);
00113 q3_dentdata = NULL;
00114 q3_entdatasize = 0;
00115 if (q3_dleafs) FreeMemory(q3_dleafs);
00116 q3_dleafs = NULL;
00117 q3_numleafs = 0;
00118 if (q3_dplanes) FreeMemory(q3_dplanes);
00119 q3_dplanes = NULL;
00120 q3_numplanes = 0;
00121 if (q3_dnodes) FreeMemory(q3_dnodes);
00122 q3_dnodes = NULL;
00123 q3_numnodes = 0;
00124 if (q3_dleafsurfaces) FreeMemory(q3_dleafsurfaces);
00125 q3_dleafsurfaces = NULL;
00126 q3_numleafsurfaces = 0;
00127 if (q3_dleafbrushes) FreeMemory(q3_dleafbrushes);
00128 q3_dleafbrushes = NULL;
00129 q3_numleafbrushes = 0;
00130 if (q3_dbrushes) FreeMemory(q3_dbrushes);
00131 q3_dbrushes = NULL;
00132 q3_numbrushes = 0;
00133 if (q3_dbrushsides) FreeMemory(q3_dbrushsides);
00134 q3_dbrushsides = NULL;
00135 q3_numbrushsides = 0;
00136 if (q3_lightBytes) FreeMemory(q3_lightBytes);
00137 q3_lightBytes = NULL;
00138 q3_numLightBytes = 0;
00139 if (q3_gridData) FreeMemory(q3_gridData);
00140 q3_gridData = NULL;
00141 q3_numGridPoints = 0;
00142 if (q3_visBytes) FreeMemory(q3_visBytes);
00143 q3_visBytes = NULL;
00144 q3_numVisBytes = 0;
00145 if (q3_drawVerts) FreeMemory(q3_drawVerts);
00146 q3_drawVerts = NULL;
00147 q3_numDrawVerts = 0;
00148 if (q3_drawIndexes) FreeMemory(q3_drawIndexes);
00149 q3_drawIndexes = NULL;
00150 q3_numDrawIndexes = 0;
00151 if (q3_drawSurfaces) FreeMemory(q3_drawSurfaces);
00152 q3_drawSurfaces = NULL;
00153 q3_numDrawSurfaces = 0;
00154 if (q3_dfogs) FreeMemory(q3_dfogs);
00155 q3_dfogs = NULL;
00156 q3_numFogs = 0;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166 void Q3_PlaneFromPoints(vec3_t p0, vec3_t p1, vec3_t p2, vec3_t normal, float *dist)
00167 {
00168 vec3_t t1, t2;
00169
00170 VectorSubtract(p0, p1, t1);
00171 VectorSubtract(p2, p1, t2);
00172 CrossProduct(t1, t2, normal);
00173 VectorNormalize(normal);
00174
00175 *dist = DotProduct(p0, normal);
00176 }
00177
00178
00179
00180
00181
00182
00183 void Q3_SurfacePlane(q3_dsurface_t *surface, vec3_t normal, float *dist)
00184 {
00185 int i;
00186 float *p0, *p1, *p2;
00187 vec3_t t1, t2;
00188
00189 p0 = q3_drawVerts[surface->firstVert].xyz;
00190 for (i = 1; i < surface->numVerts-1; i++)
00191 {
00192 p1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
00193 p2 = q3_drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz;
00194 VectorSubtract(p0, p1, t1);
00195 VectorSubtract(p2, p1, t2);
00196 CrossProduct(t1, t2, normal);
00197 VectorNormalize(normal);
00198 if (VectorLength(normal)) break;
00199 }
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 if (VectorLength(normal) < 0.9)
00219 {
00220 printf("surface %d bogus normal vector %f %f %f\n", surface - q3_drawSurfaces, normal[0], normal[1], normal[2]);
00221 printf("t1 = %f %f %f, t2 = %f %f %f\n", t1[0], t1[1], t1[2], t2[0], t2[1], t2[2]);
00222 for (i = 0; i < surface->numVerts; i++)
00223 {
00224 p1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
00225 Log_Print("p%d = %f %f %f\n", i, p1[0], p1[1], p1[2]);
00226 }
00227 }
00228 *dist = DotProduct(p0, normal);
00229 }
00230
00231
00232
00233
00234
00235
00236 q3_dplane_t *q3_surfaceplanes;
00237
00238 void Q3_CreatePlanarSurfacePlanes(void)
00239 {
00240 int i;
00241 q3_dsurface_t *surface;
00242
00243 Log_Print("creating planar surface planes...\n");
00244 q3_surfaceplanes = (q3_dplane_t *) GetClearedMemory(q3_numDrawSurfaces * sizeof(q3_dplane_t));
00245
00246 for (i = 0; i < q3_numDrawSurfaces; i++)
00247 {
00248 surface = &q3_drawSurfaces[i];
00249 if (surface->surfaceType != MST_PLANAR) continue;
00250 Q3_SurfacePlane(surface, q3_surfaceplanes[i].normal, &q3_surfaceplanes[i].dist);
00251
00252
00253
00254 }
00255 }
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280 float Q3_FaceOnWinding(q3_dsurface_t *surface, winding_t *winding)
00281 {
00282 int i;
00283 float dist, area;
00284 q3_dplane_t plane;
00285 vec_t *v1, *v2;
00286 vec3_t normal, edgevec;
00287 winding_t *w;
00288
00289
00290 w = CopyWinding(winding);
00291
00292 Q3_SurfacePlane(surface, plane.normal, &plane.dist);
00293
00294 for (i = 0; i < surface->numVerts && w; i++)
00295 {
00296 v1 = q3_drawVerts[surface->firstVert + ((i) % surface->numVerts)].xyz;
00297 v2 = q3_drawVerts[surface->firstVert + ((i+1) % surface->numVerts)].xyz;
00298
00299
00300 VectorSubtract(v2, v1, edgevec);
00301 CrossProduct(edgevec, plane.normal, normal);
00302 VectorNormalize(normal);
00303 dist = DotProduct(normal, v1);
00304
00305 ChopWindingInPlace(&w, normal, dist, -0.1);
00306 }
00307 if (w)
00308 {
00309 area = WindingArea(w);
00310 FreeWinding(w);
00311 return area;
00312 }
00313 return 0;
00314 }
00315
00316
00317
00318
00319
00320
00321
00322 winding_t *Q3_BrushSideWinding(q3_dbrush_t *brush, q3_dbrushside_t *baseside)
00323 {
00324 int i;
00325 q3_dplane_t *baseplane, *plane;
00326 winding_t *w;
00327 q3_dbrushside_t *side;
00328
00329
00330 baseplane = &q3_dplanes[baseside->planeNum];
00331 w = BaseWindingForPlane(baseplane->normal, baseplane->dist);
00332 for (i = 0; i < brush->numSides && w; i++)
00333 {
00334 side = &q3_dbrushsides[brush->firstSide + i];
00335
00336 if (side->planeNum == baseside->planeNum) continue;
00337
00338 plane = &q3_dplanes[side->planeNum];
00339 if (DotProduct(baseplane->normal, plane->normal) > 0.999
00340 && fabs(baseplane->dist - plane->dist) < 0.01) continue;
00341
00342 plane = &q3_dplanes[side->planeNum^1];
00343 ChopWindingInPlace(&w, plane->normal, plane->dist, -0.1);
00344 }
00345 return w;
00346 }
00347
00348
00349
00350
00351
00352
00353
00354 qboolean WindingIsTiny(winding_t *w);
00355
00356 void Q3_FindVisibleBrushSides(void)
00357 {
00358 int i, j, k, we, numtextured, numsides;
00359 float dot;
00360 q3_dplane_t *plane;
00361 q3_dbrushside_t *brushside;
00362 q3_dbrush_t *brush;
00363 q3_dsurface_t *surface;
00364 winding_t *w;
00365
00366 memset(q3_dbrushsidetextured, false, Q3_MAX_MAP_BRUSHSIDES);
00367
00368 numsides = 0;
00369
00370 Q3_CreatePlanarSurfacePlanes();
00371 Log_Print("searching visible brush sides...\n");
00372 Log_Print("%6d brush sides", numsides);
00373
00374 for (i = 0; i < q3_numbrushes; i++)
00375 {
00376 brush = &q3_dbrushes[i];
00377
00378 for (j = 0; j < brush->numSides; j++)
00379 {
00380 qprintf("\r%6d", numsides++);
00381 brushside = &q3_dbrushsides[brush->firstSide + j];
00382
00383 w = Q3_BrushSideWinding(brush, brushside);
00384 if (!w)
00385 {
00386 q3_dbrushsidetextured[brush->firstSide + j] = true;
00387 continue;
00388 }
00389 else
00390 {
00391
00392 if (WindingIsTiny(w))
00393 {
00394 FreeWinding(w);
00395 q3_dbrushsidetextured[brush->firstSide + j] = true;
00396 continue;
00397 }
00398 else
00399 {
00400 we = WindingError(w);
00401 if (we == WE_NOTENOUGHPOINTS
00402 || we == WE_SMALLAREA
00403 || we == WE_POINTBOGUSRANGE
00404
00405 )
00406 {
00407 FreeWinding(w);
00408 q3_dbrushsidetextured[brush->firstSide + j] = true;
00409 continue;
00410 }
00411 }
00412 }
00413 if (WindingArea(w) < 20)
00414 {
00415 q3_dbrushsidetextured[brush->firstSide + j] = true;
00416 continue;
00417 }
00418
00419 for (k = 0; k < q3_numDrawSurfaces; k++)
00420 {
00421 surface = &q3_drawSurfaces[k];
00422 if (surface->surfaceType != MST_PLANAR) continue;
00423
00424
00425 plane = &q3_surfaceplanes[k];
00426
00427 if (fabs(fabs(plane->dist) - fabs(q3_dplanes[brushside->planeNum].dist)) > 5) continue;
00428 dot = DotProduct(plane->normal, q3_dplanes[brushside->planeNum].normal);
00429 if (dot > -0.9 && dot < 0.9) continue;
00430
00431 if (Q3_FaceOnWinding(surface, w))
00432 {
00433 q3_dbrushsidetextured[brush->firstSide + j] = true;
00434
00435 break;
00436 }
00437 }
00438 FreeWinding(w);
00439 }
00440 }
00441 qprintf("\r%6d brush sides\n", numsides);
00442 numtextured = 0;
00443 for (i = 0; i < q3_numbrushsides; i++)
00444 {
00445 if (forcesidesvisible) q3_dbrushsidetextured[i] = true;
00446 if (q3_dbrushsidetextured[i]) numtextured++;
00447 }
00448 Log_Print("%d brush sides textured out of %d\n", numtextured, q3_numbrushsides);
00449 }
00450
00451
00452
00453
00454
00455
00456
00457
00458 void Q3_SwapBlock( int *block, int sizeOfBlock ) {
00459 int i;
00460
00461 sizeOfBlock >>= 2;
00462 for ( i = 0 ; i < sizeOfBlock ; i++ ) {
00463 block[i] = LittleLong( block[i] );
00464 }
00465 }
00466
00467
00468
00469
00470
00471
00472
00473
00474 void Q3_SwapBSPFile( void ) {
00475 int i;
00476
00477
00478 Q3_SwapBlock( (int *)q3_dmodels, q3_nummodels * sizeof( q3_dmodels[0] ) );
00479
00480
00481 for ( i = 0 ; i < q3_numShaders ; i++ ) {
00482 q3_dshaders[i].contentFlags = LittleLong( q3_dshaders[i].contentFlags );
00483 q3_dshaders[i].surfaceFlags = LittleLong( q3_dshaders[i].surfaceFlags );
00484 }
00485
00486
00487 Q3_SwapBlock( (int *)q3_dplanes, q3_numplanes * sizeof( q3_dplanes[0] ) );
00488
00489
00490 Q3_SwapBlock( (int *)q3_dnodes, q3_numnodes * sizeof( q3_dnodes[0] ) );
00491
00492
00493 Q3_SwapBlock( (int *)q3_dleafs, q3_numleafs * sizeof( q3_dleafs[0] ) );
00494
00495
00496 Q3_SwapBlock( (int *)q3_dleafsurfaces, q3_numleafsurfaces * sizeof( q3_dleafsurfaces[0] ) );
00497
00498
00499 Q3_SwapBlock( (int *)q3_dleafbrushes, q3_numleafbrushes * sizeof( q3_dleafbrushes[0] ) );
00500
00501
00502 Q3_SwapBlock( (int *)q3_dbrushes, q3_numbrushes * sizeof( q3_dbrushes[0] ) );
00503
00504
00505 Q3_SwapBlock( (int *)q3_dbrushsides, q3_numbrushsides * sizeof( q3_dbrushsides[0] ) );
00506
00507
00508 ((int *)&q3_visBytes)[0] = LittleLong( ((int *)&q3_visBytes)[0] );
00509 ((int *)&q3_visBytes)[1] = LittleLong( ((int *)&q3_visBytes)[1] );
00510
00511
00512 for ( i = 0 ; i < q3_numDrawVerts ; i++ ) {
00513 q3_drawVerts[i].lightmap[0] = LittleFloat( q3_drawVerts[i].lightmap[0] );
00514 q3_drawVerts[i].lightmap[1] = LittleFloat( q3_drawVerts[i].lightmap[1] );
00515 q3_drawVerts[i].st[0] = LittleFloat( q3_drawVerts[i].st[0] );
00516 q3_drawVerts[i].st[1] = LittleFloat( q3_drawVerts[i].st[1] );
00517 q3_drawVerts[i].xyz[0] = LittleFloat( q3_drawVerts[i].xyz[0] );
00518 q3_drawVerts[i].xyz[1] = LittleFloat( q3_drawVerts[i].xyz[1] );
00519 q3_drawVerts[i].xyz[2] = LittleFloat( q3_drawVerts[i].xyz[2] );
00520 q3_drawVerts[i].normal[0] = LittleFloat( q3_drawVerts[i].normal[0] );
00521 q3_drawVerts[i].normal[1] = LittleFloat( q3_drawVerts[i].normal[1] );
00522 q3_drawVerts[i].normal[2] = LittleFloat( q3_drawVerts[i].normal[2] );
00523 }
00524
00525
00526 Q3_SwapBlock( (int *)q3_drawIndexes, q3_numDrawIndexes * sizeof( q3_drawIndexes[0] ) );
00527
00528
00529 Q3_SwapBlock( (int *)q3_drawSurfaces, q3_numDrawSurfaces * sizeof( q3_drawSurfaces[0] ) );
00530
00531
00532 for ( i = 0 ; i < q3_numFogs ; i++ ) {
00533 q3_dfogs[i].brushNum = LittleLong( q3_dfogs[i].brushNum );
00534 }
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544 int Q3_CopyLump( q3_dheader_t *header, int lump, void **dest, int size ) {
00545 int length, ofs;
00546
00547 length = header->lumps[lump].filelen;
00548 ofs = header->lumps[lump].fileofs;
00549
00550 if ( length % size ) {
00551 Error ("Q3_LoadBSPFile: odd lump size");
00552 }
00553
00554 *dest = GetMemory(length);
00555
00556 memcpy( *dest, (byte *)header + ofs, length );
00557
00558 return length / size;
00559 }
00560
00561
00562
00563
00564
00565
00566 void CountTriangles( void ) {
00567 int i, numTris, numPatchTris;
00568 q3_dsurface_t *surface;
00569
00570 numTris = numPatchTris = 0;
00571 for ( i = 0; i < q3_numDrawSurfaces; i++ ) {
00572 surface = &q3_drawSurfaces[i];
00573
00574 numTris += surface->numIndexes / 3;
00575
00576 if ( surface->patchWidth ) {
00577 numPatchTris += surface->patchWidth * surface->patchHeight * 2;
00578 }
00579 }
00580
00581 Log_Print( "%6d triangles\n", numTris );
00582 Log_Print( "%6d patch tris\n", numPatchTris );
00583 }
00584
00585
00586
00587
00588
00589
00590 void Q3_LoadBSPFile(struct quakefile_s *qf)
00591 {
00592 q3_dheader_t *header;
00593
00594
00595
00596
00597 LoadQuakeFile(qf, (void **)&header);
00598
00599
00600 Q3_SwapBlock( (int *)header, sizeof(*header) );
00601
00602 if ( header->ident != Q3_BSP_IDENT ) {
00603 Error( "%s is not a IBSP file", qf->filename );
00604 }
00605 if ( header->version != Q3_BSP_VERSION ) {
00606 Error( "%s is version %i, not %i", qf->filename, header->version, Q3_BSP_VERSION );
00607 }
00608
00609 q3_numShaders = Q3_CopyLump( header, Q3_LUMP_SHADERS, (void *) &q3_dshaders, sizeof(q3_dshader_t) );
00610 q3_nummodels = Q3_CopyLump( header, Q3_LUMP_MODELS, (void *) &q3_dmodels, sizeof(q3_dmodel_t) );
00611 q3_numplanes = Q3_CopyLump( header, Q3_LUMP_PLANES, (void *) &q3_dplanes, sizeof(q3_dplane_t) );
00612 q3_numleafs = Q3_CopyLump( header, Q3_LUMP_LEAFS, (void *) &q3_dleafs, sizeof(q3_dleaf_t) );
00613 q3_numnodes = Q3_CopyLump( header, Q3_LUMP_NODES, (void *) &q3_dnodes, sizeof(q3_dnode_t) );
00614 q3_numleafsurfaces = Q3_CopyLump( header, Q3_LUMP_LEAFSURFACES, (void *) &q3_dleafsurfaces, sizeof(q3_dleafsurfaces[0]) );
00615 q3_numleafbrushes = Q3_CopyLump( header, Q3_LUMP_LEAFBRUSHES, (void *) &q3_dleafbrushes, sizeof(q3_dleafbrushes[0]) );
00616 q3_numbrushes = Q3_CopyLump( header, Q3_LUMP_BRUSHES, (void *) &q3_dbrushes, sizeof(q3_dbrush_t) );
00617 q3_numbrushsides = Q3_CopyLump( header, Q3_LUMP_BRUSHSIDES, (void *) &q3_dbrushsides, sizeof(q3_dbrushside_t) );
00618 q3_numDrawVerts = Q3_CopyLump( header, Q3_LUMP_DRAWVERTS, (void *) &q3_drawVerts, sizeof(q3_drawVert_t) );
00619 q3_numDrawSurfaces = Q3_CopyLump( header, Q3_LUMP_SURFACES, (void *) &q3_drawSurfaces, sizeof(q3_dsurface_t) );
00620 q3_numFogs = Q3_CopyLump( header, Q3_LUMP_FOGS, (void *) &q3_dfogs, sizeof(q3_dfog_t) );
00621 q3_numDrawIndexes = Q3_CopyLump( header, Q3_LUMP_DRAWINDEXES, (void *) &q3_drawIndexes, sizeof(q3_drawIndexes[0]) );
00622
00623 q3_numVisBytes = Q3_CopyLump( header, Q3_LUMP_VISIBILITY, (void *) &q3_visBytes, 1 );
00624 q3_numLightBytes = Q3_CopyLump( header, Q3_LUMP_LIGHTMAPS, (void *) &q3_lightBytes, 1 );
00625 q3_entdatasize = Q3_CopyLump( header, Q3_LUMP_ENTITIES, (void *) &q3_dentdata, 1);
00626
00627 q3_numGridPoints = Q3_CopyLump( header, Q3_LUMP_LIGHTGRID, (void *) &q3_gridData, 8 );
00628
00629 CountTriangles();
00630
00631 FreeMemory( header );
00632
00633
00634 Q3_SwapBSPFile();
00635
00636 Q3_FindVisibleBrushSides();
00637
00638
00639 }
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649 void Q3_AddLump( FILE *bspfile, q3_dheader_t *header, int lumpnum, void *data, int len ) {
00650 q3_lump_t *lump;
00651
00652 lump = &header->lumps[lumpnum];
00653
00654 lump->fileofs = LittleLong( ftell(bspfile) );
00655 lump->filelen = LittleLong( len );
00656 SafeWrite( bspfile, data, (len+3)&~3 );
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666 void Q3_WriteBSPFile( char *filename )
00667 {
00668 q3_dheader_t outheader, *header;
00669 FILE *bspfile;
00670
00671 header = &outheader;
00672 memset( header, 0, sizeof(q3_dheader_t) );
00673
00674 Q3_SwapBSPFile();
00675
00676 header->ident = LittleLong( Q3_BSP_IDENT );
00677 header->version = LittleLong( Q3_BSP_VERSION );
00678
00679 bspfile = SafeOpenWrite( filename );
00680 SafeWrite( bspfile, header, sizeof(q3_dheader_t) );
00681
00682 Q3_AddLump( bspfile, header, Q3_LUMP_SHADERS, q3_dshaders, q3_numShaders*sizeof(q3_dshader_t) );
00683 Q3_AddLump( bspfile, header, Q3_LUMP_PLANES, q3_dplanes, q3_numplanes*sizeof(q3_dplane_t) );
00684 Q3_AddLump( bspfile, header, Q3_LUMP_LEAFS, q3_dleafs, q3_numleafs*sizeof(q3_dleaf_t) );
00685 Q3_AddLump( bspfile, header, Q3_LUMP_NODES, q3_dnodes, q3_numnodes*sizeof(q3_dnode_t) );
00686 Q3_AddLump( bspfile, header, Q3_LUMP_BRUSHES, q3_dbrushes, q3_numbrushes*sizeof(q3_dbrush_t) );
00687 Q3_AddLump( bspfile, header, Q3_LUMP_BRUSHSIDES, q3_dbrushsides, q3_numbrushsides*sizeof(q3_dbrushside_t) );
00688 Q3_AddLump( bspfile, header, Q3_LUMP_LEAFSURFACES, q3_dleafsurfaces, q3_numleafsurfaces*sizeof(q3_dleafsurfaces[0]) );
00689 Q3_AddLump( bspfile, header, Q3_LUMP_LEAFBRUSHES, q3_dleafbrushes, q3_numleafbrushes*sizeof(q3_dleafbrushes[0]) );
00690 Q3_AddLump( bspfile, header, Q3_LUMP_MODELS, q3_dmodels, q3_nummodels*sizeof(q3_dmodel_t) );
00691 Q3_AddLump( bspfile, header, Q3_LUMP_DRAWVERTS, q3_drawVerts, q3_numDrawVerts*sizeof(q3_drawVert_t) );
00692 Q3_AddLump( bspfile, header, Q3_LUMP_SURFACES, q3_drawSurfaces, q3_numDrawSurfaces*sizeof(q3_dsurface_t) );
00693 Q3_AddLump( bspfile, header, Q3_LUMP_VISIBILITY, q3_visBytes, q3_numVisBytes );
00694 Q3_AddLump( bspfile, header, Q3_LUMP_LIGHTMAPS, q3_lightBytes, q3_numLightBytes );
00695 Q3_AddLump( bspfile, header, Q3_LUMP_LIGHTGRID, q3_gridData, 8 * q3_numGridPoints );
00696 Q3_AddLump( bspfile, header, Q3_LUMP_ENTITIES, q3_dentdata, q3_entdatasize );
00697 Q3_AddLump( bspfile, header, Q3_LUMP_FOGS, q3_dfogs, q3_numFogs * sizeof(q3_dfog_t) );
00698 Q3_AddLump( bspfile, header, Q3_LUMP_DRAWINDEXES, q3_drawIndexes, q3_numDrawIndexes * sizeof(q3_drawIndexes[0]) );
00699
00700 fseek (bspfile, 0, SEEK_SET);
00701 SafeWrite (bspfile, header, sizeof(q3_dheader_t));
00702 fclose (bspfile);
00703 }
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714 void Q3_PrintBSPFileSizes( void )
00715 {
00716 if ( !num_entities )
00717 {
00718 Q3_ParseEntities();
00719 }
00720
00721 Log_Print ("%6i models %7i\n"
00722 ,q3_nummodels, (int)(q3_nummodels*sizeof(q3_dmodel_t)));
00723 Log_Print ("%6i shaders %7i\n"
00724 ,q3_numShaders, (int)(q3_numShaders*sizeof(q3_dshader_t)));
00725 Log_Print ("%6i brushes %7i\n"
00726 ,q3_numbrushes, (int)(q3_numbrushes*sizeof(q3_dbrush_t)));
00727 Log_Print ("%6i brushsides %7i\n"
00728 ,q3_numbrushsides, (int)(q3_numbrushsides*sizeof(q3_dbrushside_t)));
00729 Log_Print ("%6i fogs %7i\n"
00730 ,q3_numFogs, (int)(q3_numFogs*sizeof(q3_dfog_t)));
00731 Log_Print ("%6i planes %7i\n"
00732 ,q3_numplanes, (int)(q3_numplanes*sizeof(q3_dplane_t)));
00733 Log_Print ("%6i entdata %7i\n", num_entities, q3_entdatasize);
00734
00735 Log_Print ("\n");
00736
00737 Log_Print ("%6i nodes %7i\n"
00738 ,q3_numnodes, (int)(q3_numnodes*sizeof(q3_dnode_t)));
00739 Log_Print ("%6i leafs %7i\n"
00740 ,q3_numleafs, (int)(q3_numleafs*sizeof(q3_dleaf_t)));
00741 Log_Print ("%6i leafsurfaces %7i\n"
00742 ,q3_numleafsurfaces, (int)(q3_numleafsurfaces*sizeof(q3_dleafsurfaces[0])));
00743 Log_Print ("%6i leafbrushes %7i\n"
00744 ,q3_numleafbrushes, (int)(q3_numleafbrushes*sizeof(q3_dleafbrushes[0])));
00745 Log_Print ("%6i drawverts %7i\n"
00746 ,q3_numDrawVerts, (int)(q3_numDrawVerts*sizeof(q3_drawVerts[0])));
00747 Log_Print ("%6i drawindexes %7i\n"
00748 ,q3_numDrawIndexes, (int)(q3_numDrawIndexes*sizeof(q3_drawIndexes[0])));
00749 Log_Print ("%6i drawsurfaces %7i\n"
00750 ,q3_numDrawSurfaces, (int)(q3_numDrawSurfaces*sizeof(q3_drawSurfaces[0])));
00751
00752 Log_Print ("%6i lightmaps %7i\n"
00753 ,q3_numLightBytes / (LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT*3), q3_numLightBytes );
00754 Log_Print (" visibility %7i\n"
00755 , q3_numVisBytes );
00756 }
00757
00758
00759
00760
00761
00762
00763
00764
00765 void Q3_ParseEntities (void)
00766 {
00767 script_t *script;
00768
00769 num_entities = 0;
00770 script = LoadScriptMemory(q3_dentdata, q3_entdatasize, "*Quake3 bsp file");
00771 SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES |
00772 SCFL_NOSTRINGESCAPECHARS);
00773
00774 while(ParseEntity(script))
00775 {
00776 }
00777
00778 FreeScript(script);
00779 }
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789 void Q3_UnparseEntities (void)
00790 {
00791 char *buf, *end;
00792 epair_t *ep;
00793 char line[2048];
00794 int i;
00795
00796 buf = q3_dentdata;
00797 end = buf;
00798 *end = 0;
00799
00800 for (i=0 ; i<num_entities ; i++)
00801 {
00802 ep = entities[i].epairs;
00803 if (!ep)
00804 continue;
00805
00806 strcat (end,"{\n");
00807 end += 2;
00808
00809 for (ep = entities[i].epairs ; ep ; ep=ep->next)
00810 {
00811 sprintf (line, "\"%s\" \"%s\"\n", ep->key, ep->value);
00812 strcat (end, line);
00813 end += strlen(line);
00814 }
00815 strcat (end,"}\n");
00816 end += 2;
00817
00818 if (end > buf + Q3_MAX_MAP_ENTSTRING)
00819 Error ("Entity text too long");
00820 }
00821 q3_entdatasize = end - buf + 1;
00822 }
00823
00824