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 "q2files.h"
00030 #include "l_bsp_q2.h"
00031 #include "l_bsp_ent.h"
00032
00033 #define q2_dmodel_t dmodel_t
00034 #define q2_lump_t lump_t
00035 #define q2_dheader_t dheader_t
00036 #define q2_dmodel_t dmodel_t
00037 #define q2_dvertex_t dvertex_t
00038 #define q2_dplane_t dplane_t
00039 #define q2_dnode_t dnode_t
00040 #define q2_texinfo_t texinfo_t
00041 #define q2_dedge_t dedge_t
00042 #define q2_dface_t dface_t
00043 #define q2_dleaf_t dleaf_t
00044 #define q2_dbrushside_t dbrushside_t
00045 #define q2_dbrush_t dbrush_t
00046 #define q2_dvis_t dvis_t
00047 #define q2_dareaportal_t dareaportal_t
00048 #define q2_darea_t darea_t
00049
00050 #define q2_nummodels nummodels
00051 #define q2_dmodels dmodels
00052 #define q2_numleafs numleafs
00053 #define q2_dleafs dleafs
00054 #define q2_numplanes numplanes
00055 #define q2_dplanes dplanes
00056 #define q2_numvertexes numvertexes
00057 #define q2_dvertexes dvertexes
00058 #define q2_numnodes numnodes
00059 #define q2_dnodes dnodes
00060 #define q2_numtexinfo numtexinfo
00061 #define q2_texinfo texinfo
00062 #define q2_numfaces numfaces
00063 #define q2_dfaces dfaces
00064 #define q2_numedges numedges
00065 #define q2_dedges dedges
00066 #define q2_numleaffaces numleaffaces
00067 #define q2_dleaffaces dleaffaces
00068 #define q2_numleafbrushes numleafbrushes
00069 #define q2_dleafbrushes dleafbrushes
00070 #define q2_dsurfedges dsurfedges
00071 #define q2_numbrushes numbrushes
00072 #define q2_dbrushes dbrushes
00073 #define q2_numbrushsides numbrushsides
00074 #define q2_dbrushsides dbrushsides
00075 #define q2_numareas numareas
00076 #define q2_dareas dareas
00077 #define q2_numareaportals numareaportals
00078 #define q2_dareaportals dareaportals
00079
00080 void GetLeafNums (void);
00081
00082
00083
00084 int nummodels;
00085 dmodel_t *dmodels;
00086
00087 int visdatasize;
00088 byte *dvisdata;
00089 dvis_t *dvis;
00090
00091 int lightdatasize;
00092 byte *dlightdata;
00093
00094 int entdatasize;
00095 char *dentdata;
00096
00097 int numleafs;
00098 dleaf_t *dleafs;
00099
00100 int numplanes;
00101 dplane_t *dplanes;
00102
00103 int numvertexes;
00104 dvertex_t *dvertexes;
00105
00106 int numnodes;
00107 dnode_t *dnodes;
00108
00109
00110 int numtexinfo;
00111 texinfo_t texinfo[MAX_MAP_TEXINFO];
00112
00113 int numfaces;
00114 dface_t *dfaces;
00115
00116 int numedges;
00117 dedge_t *dedges;
00118
00119 int numleaffaces;
00120 unsigned short *dleaffaces;
00121
00122 int numleafbrushes;
00123 unsigned short *dleafbrushes;
00124
00125 int numsurfedges;
00126 int *dsurfedges;
00127
00128 int numbrushes;
00129 dbrush_t *dbrushes;
00130
00131 int numbrushsides;
00132 dbrushside_t *dbrushsides;
00133
00134 int numareas;
00135 darea_t *dareas;
00136
00137 int numareaportals;
00138 dareaportal_t *dareaportals;
00139
00140 #define MAX_MAP_DPOP 256
00141 byte dpop[MAX_MAP_DPOP];
00142
00143
00144 char brushsidetextured[MAX_MAP_BRUSHSIDES];
00145
00146
00147
00148 int bspallocated = false;
00149 int allocatedbspmem = 0;
00150
00151 void Q2_AllocMaxBSP(void)
00152 {
00153
00154 nummodels = 0;
00155 dmodels = (dmodel_t *) GetClearedMemory(MAX_MAP_MODELS * sizeof(dmodel_t));
00156 allocatedbspmem += MAX_MAP_MODELS * sizeof(dmodel_t);
00157
00158 visdatasize = 0;
00159 dvisdata = (byte *) GetClearedMemory(MAX_MAP_VISIBILITY * sizeof(byte));
00160 dvis = (dvis_t *) dvisdata;
00161 allocatedbspmem += MAX_MAP_VISIBILITY * sizeof(byte);
00162
00163 lightdatasize = 0;
00164 dlightdata = (byte *) GetClearedMemory(MAX_MAP_LIGHTING * sizeof(byte));
00165 allocatedbspmem += MAX_MAP_LIGHTING * sizeof(byte);
00166
00167 entdatasize = 0;
00168 dentdata = (char *) GetClearedMemory(MAX_MAP_ENTSTRING * sizeof(char));
00169 allocatedbspmem += MAX_MAP_ENTSTRING * sizeof(char);
00170
00171 numleafs = 0;
00172 dleafs = (dleaf_t *) GetClearedMemory(MAX_MAP_LEAFS * sizeof(dleaf_t));
00173 allocatedbspmem += MAX_MAP_LEAFS * sizeof(dleaf_t);
00174
00175 numplanes = 0;
00176 dplanes = (dplane_t *) GetClearedMemory(MAX_MAP_PLANES * sizeof(dplane_t));
00177 allocatedbspmem += MAX_MAP_PLANES * sizeof(dplane_t);
00178
00179 numvertexes = 0;
00180 dvertexes = (dvertex_t *) GetClearedMemory(MAX_MAP_VERTS * sizeof(dvertex_t));
00181 allocatedbspmem += MAX_MAP_VERTS * sizeof(dvertex_t);
00182
00183 numnodes = 0;
00184 dnodes = (dnode_t *) GetClearedMemory(MAX_MAP_NODES * sizeof(dnode_t));
00185 allocatedbspmem += MAX_MAP_NODES * sizeof(dnode_t);
00186
00187
00188
00189
00190
00191
00192
00193 numfaces = 0;
00194 dfaces = (dface_t *) GetClearedMemory(MAX_MAP_FACES * sizeof(dface_t));
00195 allocatedbspmem += MAX_MAP_FACES * sizeof(dface_t);
00196
00197 numedges = 0;
00198 dedges = (dedge_t *) GetClearedMemory(MAX_MAP_EDGES * sizeof(dedge_t));
00199 allocatedbspmem += MAX_MAP_EDGES * sizeof(dedge_t);
00200
00201 numleaffaces = 0;
00202 dleaffaces = (unsigned short *) GetClearedMemory(MAX_MAP_LEAFFACES * sizeof(unsigned short));
00203 allocatedbspmem += MAX_MAP_LEAFFACES * sizeof(unsigned short);
00204
00205 numleafbrushes = 0;
00206 dleafbrushes = (unsigned short *) GetClearedMemory(MAX_MAP_LEAFBRUSHES * sizeof(unsigned short));
00207 allocatedbspmem += MAX_MAP_LEAFBRUSHES * sizeof(unsigned short);
00208
00209 numsurfedges = 0;
00210 dsurfedges = (int *) GetClearedMemory(MAX_MAP_SURFEDGES * sizeof(int));
00211 allocatedbspmem += MAX_MAP_SURFEDGES * sizeof(int);
00212
00213 numbrushes = 0;
00214 dbrushes = (dbrush_t *) GetClearedMemory(MAX_MAP_BRUSHES * sizeof(dbrush_t));
00215 allocatedbspmem += MAX_MAP_BRUSHES * sizeof(dbrush_t);
00216
00217 numbrushsides = 0;
00218 dbrushsides = (dbrushside_t *) GetClearedMemory(MAX_MAP_BRUSHSIDES * sizeof(dbrushside_t));
00219 allocatedbspmem += MAX_MAP_BRUSHSIDES * sizeof(dbrushside_t);
00220
00221 numareas = 0;
00222 dareas = (darea_t *) GetClearedMemory(MAX_MAP_AREAS * sizeof(darea_t));
00223 allocatedbspmem += MAX_MAP_AREAS * sizeof(darea_t);
00224
00225 numareaportals = 0;
00226 dareaportals = (dareaportal_t *) GetClearedMemory(MAX_MAP_AREAPORTALS * sizeof(dareaportal_t));
00227 allocatedbspmem += MAX_MAP_AREAPORTALS * sizeof(dareaportal_t);
00228
00229 Log_Print("allocated ");
00230 PrintMemorySize(allocatedbspmem);
00231 Log_Print(" of BSP memory\n");
00232 }
00233
00234 void Q2_FreeMaxBSP(void)
00235 {
00236
00237 nummodels = 0;
00238 FreeMemory(dmodels);
00239 dmodels = NULL;
00240
00241 visdatasize = 0;
00242 FreeMemory(dvisdata);
00243 dvisdata = NULL;
00244 dvis = NULL;
00245
00246 lightdatasize = 0;
00247 FreeMemory(dlightdata);
00248 dlightdata = NULL;
00249
00250 entdatasize = 0;
00251 FreeMemory(dentdata);
00252 dentdata = NULL;
00253
00254 numleafs = 0;
00255 FreeMemory(dleafs);
00256 dleafs = NULL;
00257
00258 numplanes = 0;
00259 FreeMemory(dplanes);
00260 dplanes = NULL;
00261
00262 numvertexes = 0;
00263 FreeMemory(dvertexes);
00264 dvertexes = NULL;
00265
00266 numnodes = 0;
00267 FreeMemory(dnodes);
00268 dnodes = NULL;
00269
00270
00271
00272
00273
00274
00275
00276 numfaces = 0;
00277 FreeMemory(dfaces);
00278 dfaces = NULL;
00279
00280 numedges = 0;
00281 FreeMemory(dedges);
00282 dedges = NULL;
00283
00284 numleaffaces = 0;
00285 FreeMemory(dleaffaces);
00286 dleaffaces = NULL;
00287
00288 numleafbrushes = 0;
00289 FreeMemory(dleafbrushes);
00290 dleafbrushes = NULL;
00291
00292 numsurfedges = 0;
00293 FreeMemory(dsurfedges);
00294 dsurfedges = NULL;
00295
00296 numbrushes = 0;
00297 FreeMemory(dbrushes);
00298 dbrushes = NULL;
00299
00300 numbrushsides = 0;
00301 FreeMemory(dbrushsides);
00302 dbrushsides = NULL;
00303
00304 numareas = 0;
00305 FreeMemory(dareas);
00306 dareas = NULL;
00307
00308 numareaportals = 0;
00309 FreeMemory(dareaportals);
00310 dareaportals = NULL;
00311
00312 Log_Print("freed ");
00313 PrintMemorySize(allocatedbspmem);
00314 Log_Print(" of BSP memory\n");
00315 allocatedbspmem = 0;
00316 }
00317
00318 #define WCONVEX_EPSILON 0.5
00319
00320 int InsideWinding(winding_t *w, vec3_t point, int planenum)
00321 {
00322 int i;
00323 float dist;
00324 vec_t *v1, *v2;
00325 vec3_t normal, edgevec;
00326 dplane_t *plane;
00327
00328 for (i = 1; i <= w->numpoints; i++)
00329 {
00330 v1 = w->p[i % w->numpoints];
00331 v2 = w->p[(i + 1) % w->numpoints];
00332
00333 VectorSubtract(v2, v1, edgevec);
00334 plane = &dplanes[planenum];
00335 CrossProduct(plane->normal, edgevec, normal);
00336 VectorNormalize(normal);
00337 dist = DotProduct(normal, v1);
00338
00339 if (DotProduct(normal, point) - dist > WCONVEX_EPSILON) return false;
00340 }
00341 return true;
00342 }
00343
00344 int InsideFace(dface_t *face, vec3_t point)
00345 {
00346 int i, edgenum, side;
00347 float dist;
00348 vec_t *v1, *v2;
00349 vec3_t normal, edgevec;
00350 dplane_t *plane;
00351
00352 for (i = 0; i < face->numedges; i++)
00353 {
00354
00355 edgenum = dsurfedges[face->firstedge + i];
00356 side = edgenum < 0;
00357 v1 = dvertexes[dedges[abs(edgenum)].v[side]].point;
00358 v2 = dvertexes[dedges[abs(edgenum)].v[!side]].point;
00359
00360
00361 VectorSubtract(v1, v2, edgevec);
00362 plane = &dplanes[face->planenum];
00363 CrossProduct(plane->normal, edgevec, normal);
00364 VectorNormalize(normal);
00365 dist = DotProduct(normal, v1);
00366
00367 if (DotProduct(normal, point) - dist > WCONVEX_EPSILON) return false;
00368 }
00369 return true;
00370 }
00371
00372
00373
00374
00375
00376
00377
00378 float Q2_FaceOnWinding(q2_dface_t *face, winding_t *winding)
00379 {
00380 int i, edgenum, side;
00381 float dist, area;
00382 q2_dplane_t plane;
00383 vec_t *v1, *v2;
00384 vec3_t normal, edgevec;
00385 winding_t *w;
00386
00387
00388 w = CopyWinding(winding);
00389 memcpy(&plane, &q2_dplanes[face->planenum], sizeof(q2_dplane_t));
00390
00391 if (face->side)
00392 {
00393 VectorNegate(plane.normal, plane.normal);
00394 plane.dist = -plane.dist;
00395 }
00396 for (i = 0; i < face->numedges && w; i++)
00397 {
00398
00399 edgenum = q2_dsurfedges[face->firstedge + i];
00400 side = edgenum > 0;
00401
00402 v1 = q2_dvertexes[q2_dedges[abs(edgenum)].v[side]].point;
00403 v2 = q2_dvertexes[q2_dedges[abs(edgenum)].v[!side]].point;
00404
00405
00406 VectorSubtract(v1, v2, edgevec);
00407 CrossProduct(edgevec, plane.normal, normal);
00408 VectorNormalize(normal);
00409 dist = DotProduct(normal, v1);
00410
00411 ChopWindingInPlace(&w, normal, dist, -0.1);
00412 }
00413 if (w)
00414 {
00415 area = WindingArea(w);
00416 FreeWinding(w);
00417 return area;
00418 }
00419 return 0;
00420 }
00421
00422
00423
00424
00425
00426
00427
00428 winding_t *Q2_BrushSideWinding(dbrush_t *brush, dbrushside_t *baseside)
00429 {
00430 int i;
00431 dplane_t *baseplane, *plane;
00432 winding_t *w;
00433 dbrushside_t *side;
00434
00435
00436 baseplane = &dplanes[baseside->planenum];
00437 w = BaseWindingForPlane(baseplane->normal, baseplane->dist);
00438 for (i = 0; i < brush->numsides && w; i++)
00439 {
00440 side = &dbrushsides[brush->firstside + i];
00441
00442 if (side->planenum == baseside->planenum) continue;
00443
00444 plane = &dplanes[side->planenum];
00445 if (DotProduct(baseplane->normal, plane->normal) > 0.999
00446 && fabs(baseplane->dist - plane->dist) < 0.01) continue;
00447
00448 plane = &dplanes[side->planenum^1];
00449 ChopWindingInPlace(&w, plane->normal, plane->dist, -0.1);
00450 }
00451 return w;
00452 }
00453
00454
00455
00456
00457
00458
00459 int Q2_HintSkipBrush(dbrush_t *brush)
00460 {
00461 int j;
00462 dbrushside_t *brushside;
00463
00464 for (j = 0; j < brush->numsides; j++)
00465 {
00466 brushside = &dbrushsides[brush->firstside + j];
00467 if (brushside->texinfo > 0)
00468 {
00469 if (texinfo[brushside->texinfo].flags & (SURF_SKIP|SURF_HINT))
00470 {
00471 return true;
00472 }
00473 }
00474 }
00475 return false;
00476 }
00477
00478
00479
00480
00481
00482
00483
00484 qboolean WindingIsTiny(winding_t *w);
00485
00486 void Q2_FixTextureReferences(void)
00487 {
00488 int i, j, k, we;
00489 dbrushside_t *brushside;
00490 dbrush_t *brush;
00491 dface_t *face;
00492 winding_t *w;
00493
00494 memset(brushsidetextured, false, MAX_MAP_BRUSHSIDES);
00495
00496 for (i = 0; i < numbrushes; i++)
00497 {
00498 brush = &dbrushes[i];
00499
00500 if (Q2_HintSkipBrush(brush)) continue;
00501
00502 for (j = 0; j < brush->numsides; j++)
00503 {
00504 brushside = &dbrushsides[brush->firstside + j];
00505
00506 w = Q2_BrushSideWinding(brush, brushside);
00507 if (!w)
00508 {
00509 brushsidetextured[brush->firstside + j] = true;
00510 continue;
00511 }
00512 else
00513 {
00514
00515 if (WindingIsTiny(w))
00516 {
00517 FreeWinding(w);
00518 brushsidetextured[brush->firstside + j] = true;
00519 continue;
00520 }
00521 else
00522 {
00523 we = WindingError(w);
00524 if (we == WE_NOTENOUGHPOINTS
00525 || we == WE_SMALLAREA
00526 || we == WE_POINTBOGUSRANGE
00527
00528 )
00529 {
00530 FreeWinding(w);
00531 brushsidetextured[brush->firstside + j] = true;
00532 continue;
00533 }
00534 }
00535 }
00536 if (WindingArea(w) < 20)
00537 {
00538 brushsidetextured[brush->firstside + j] = true;
00539 }
00540
00541 for (k = 0; k < numfaces; k++)
00542 {
00543 face = &dfaces[k];
00544
00545 if ((face->planenum&~1) != (brushside->planenum&~1)) continue;
00546
00547 if (Q2_FaceOnWinding(face, w))
00548 {
00549 brushside->texinfo = face->texinfo;
00550 brushsidetextured[brush->firstside + j] = true;
00551 break;
00552 }
00553 }
00554 FreeWinding(w);
00555 }
00556 }
00557 }
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 int Q2_CompressVis (byte *vis, byte *dest)
00569 {
00570 int j;
00571 int rep;
00572 int visrow;
00573 byte *dest_p;
00574
00575 dest_p = dest;
00576
00577 visrow = (dvis->numclusters + 7)>>3;
00578
00579 for (j=0 ; j<visrow ; j++)
00580 {
00581 *dest_p++ = vis[j];
00582 if (vis[j])
00583 continue;
00584
00585 rep = 1;
00586 for ( j++; j<visrow ; j++)
00587 if (vis[j] || rep == 255)
00588 break;
00589 else
00590 rep++;
00591 *dest_p++ = rep;
00592 j--;
00593 }
00594
00595 return dest_p - dest;
00596 }
00597
00598
00599
00600
00601
00602
00603
00604 void Q2_DecompressVis (byte *in, byte *decompressed)
00605 {
00606 int c;
00607 byte *out;
00608 int row;
00609
00610
00611 row = (dvis->numclusters+7)>>3;
00612 out = decompressed;
00613
00614 do
00615 {
00616 if (*in)
00617 {
00618 *out++ = *in++;
00619 continue;
00620 }
00621
00622 c = in[1];
00623 if (!c)
00624 Error ("DecompressVis: 0 repeat");
00625 in += 2;
00626 while (c)
00627 {
00628 *out++ = 0;
00629 c--;
00630 }
00631 } while (out - decompressed < row);
00632 }
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643 void Q2_SwapBSPFile (qboolean todisk)
00644 {
00645 int i, j;
00646 dmodel_t *d;
00647
00648
00649
00650 for (i=0 ; i<nummodels ; i++)
00651 {
00652 d = &dmodels[i];
00653
00654 d->firstface = LittleLong (d->firstface);
00655 d->numfaces = LittleLong (d->numfaces);
00656 d->headnode = LittleLong (d->headnode);
00657
00658 for (j=0 ; j<3 ; j++)
00659 {
00660 d->mins[j] = LittleFloat(d->mins[j]);
00661 d->maxs[j] = LittleFloat(d->maxs[j]);
00662 d->origin[j] = LittleFloat(d->origin[j]);
00663 }
00664 }
00665
00666
00667
00668
00669 for (i=0 ; i<numvertexes ; i++)
00670 {
00671 for (j=0 ; j<3 ; j++)
00672 dvertexes[i].point[j] = LittleFloat (dvertexes[i].point[j]);
00673 }
00674
00675
00676
00677
00678 for (i=0 ; i<numplanes ; i++)
00679 {
00680 for (j=0 ; j<3 ; j++)
00681 dplanes[i].normal[j] = LittleFloat (dplanes[i].normal[j]);
00682 dplanes[i].dist = LittleFloat (dplanes[i].dist);
00683 dplanes[i].type = LittleLong (dplanes[i].type);
00684 }
00685
00686
00687
00688
00689 for (i=0 ; i<numtexinfo ; i++)
00690 {
00691 for (j=0 ; j<8 ; j++)
00692 texinfo[i].vecs[0][j] = LittleFloat (texinfo[i].vecs[0][j]);
00693 texinfo[i].flags = LittleLong (texinfo[i].flags);
00694 texinfo[i].value = LittleLong (texinfo[i].value);
00695 texinfo[i].nexttexinfo = LittleLong (texinfo[i].nexttexinfo);
00696 }
00697
00698
00699
00700
00701 for (i=0 ; i<numfaces ; i++)
00702 {
00703 dfaces[i].texinfo = LittleShort (dfaces[i].texinfo);
00704 dfaces[i].planenum = LittleShort (dfaces[i].planenum);
00705 dfaces[i].side = LittleShort (dfaces[i].side);
00706 dfaces[i].lightofs = LittleLong (dfaces[i].lightofs);
00707 dfaces[i].firstedge = LittleLong (dfaces[i].firstedge);
00708 dfaces[i].numedges = LittleShort (dfaces[i].numedges);
00709 }
00710
00711
00712
00713
00714 for (i=0 ; i<numnodes ; i++)
00715 {
00716 dnodes[i].planenum = LittleLong (dnodes[i].planenum);
00717 for (j=0 ; j<3 ; j++)
00718 {
00719 dnodes[i].mins[j] = LittleShort (dnodes[i].mins[j]);
00720 dnodes[i].maxs[j] = LittleShort (dnodes[i].maxs[j]);
00721 }
00722 dnodes[i].children[0] = LittleLong (dnodes[i].children[0]);
00723 dnodes[i].children[1] = LittleLong (dnodes[i].children[1]);
00724 dnodes[i].firstface = LittleShort (dnodes[i].firstface);
00725 dnodes[i].numfaces = LittleShort (dnodes[i].numfaces);
00726 }
00727
00728
00729
00730
00731 for (i=0 ; i<numleafs ; i++)
00732 {
00733 dleafs[i].contents = LittleLong (dleafs[i].contents);
00734 dleafs[i].cluster = LittleShort (dleafs[i].cluster);
00735 dleafs[i].area = LittleShort (dleafs[i].area);
00736 for (j=0 ; j<3 ; j++)
00737 {
00738 dleafs[i].mins[j] = LittleShort (dleafs[i].mins[j]);
00739 dleafs[i].maxs[j] = LittleShort (dleafs[i].maxs[j]);
00740 }
00741
00742 dleafs[i].firstleafface = LittleShort (dleafs[i].firstleafface);
00743 dleafs[i].numleaffaces = LittleShort (dleafs[i].numleaffaces);
00744 dleafs[i].firstleafbrush = LittleShort (dleafs[i].firstleafbrush);
00745 dleafs[i].numleafbrushes = LittleShort (dleafs[i].numleafbrushes);
00746 }
00747
00748
00749
00750
00751 for (i=0 ; i<numleaffaces ; i++)
00752 dleaffaces[i] = LittleShort (dleaffaces[i]);
00753
00754
00755
00756
00757 for (i=0 ; i<numleafbrushes ; i++)
00758 dleafbrushes[i] = LittleShort (dleafbrushes[i]);
00759
00760
00761
00762
00763 for (i=0 ; i<numsurfedges ; i++)
00764 dsurfedges[i] = LittleLong (dsurfedges[i]);
00765
00766
00767
00768
00769 for (i=0 ; i<numedges ; i++)
00770 {
00771 dedges[i].v[0] = LittleShort (dedges[i].v[0]);
00772 dedges[i].v[1] = LittleShort (dedges[i].v[1]);
00773 }
00774
00775
00776
00777
00778 for (i=0 ; i<numbrushes ; i++)
00779 {
00780 dbrushes[i].firstside = LittleLong (dbrushes[i].firstside);
00781 dbrushes[i].numsides = LittleLong (dbrushes[i].numsides);
00782 dbrushes[i].contents = LittleLong (dbrushes[i].contents);
00783 }
00784
00785
00786
00787
00788 for (i=0 ; i<numareas ; i++)
00789 {
00790 dareas[i].numareaportals = LittleLong (dareas[i].numareaportals);
00791 dareas[i].firstareaportal = LittleLong (dareas[i].firstareaportal);
00792 }
00793
00794
00795
00796
00797 for (i=0 ; i<numareaportals ; i++)
00798 {
00799 dareaportals[i].portalnum = LittleLong (dareaportals[i].portalnum);
00800 dareaportals[i].otherarea = LittleLong (dareaportals[i].otherarea);
00801 }
00802
00803
00804
00805
00806 for (i=0 ; i<numbrushsides ; i++)
00807 {
00808 dbrushsides[i].planenum = LittleShort (dbrushsides[i].planenum);
00809 dbrushsides[i].texinfo = LittleShort (dbrushsides[i].texinfo);
00810 }
00811
00812
00813
00814
00815 if (todisk)
00816 j = dvis->numclusters;
00817 else
00818 j = LittleLong(dvis->numclusters);
00819 dvis->numclusters = LittleLong (dvis->numclusters);
00820 for (i=0 ; i<j ; i++)
00821 {
00822 dvis->bitofs[i][0] = LittleLong (dvis->bitofs[i][0]);
00823 dvis->bitofs[i][1] = LittleLong (dvis->bitofs[i][1]);
00824 }
00825 }
00826
00827
00828 dheader_t *header;
00829
00830 int Q2_CopyLump (int lump, void *dest, int size, int maxsize)
00831 {
00832 int length, ofs;
00833
00834 length = header->lumps[lump].filelen;
00835 ofs = header->lumps[lump].fileofs;
00836
00837 if (length % size)
00838 Error ("LoadBSPFile: odd lump size");
00839
00840 if ((length/size) > maxsize)
00841 Error ("Q2_LoadBSPFile: exceeded max size for lump %d size %d > maxsize %d\n", lump, (length/size), maxsize);
00842
00843 memcpy (dest, (byte *)header + ofs, length);
00844
00845 return length / size;
00846 }
00847
00848
00849
00850
00851
00852
00853 void Q2_LoadBSPFile(char *filename, int offset, int length)
00854 {
00855 int i;
00856
00857
00858
00859
00860 LoadFile (filename, (void **)&header, offset, length);
00861
00862
00863 for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
00864 ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
00865
00866 if (header->ident != IDBSPHEADER)
00867 Error ("%s is not a IBSP file", filename);
00868 if (header->version != BSPVERSION)
00869 Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
00870
00871 nummodels = Q2_CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t), MAX_MAP_MODELS);
00872 numvertexes = Q2_CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t), MAX_MAP_VERTS);
00873 numplanes = Q2_CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t), MAX_MAP_PLANES);
00874 numleafs = Q2_CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t), MAX_MAP_LEAFS);
00875 numnodes = Q2_CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t), MAX_MAP_NODES);
00876 numtexinfo = Q2_CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t), MAX_MAP_TEXINFO);
00877 numfaces = Q2_CopyLump (LUMP_FACES, dfaces, sizeof(dface_t), MAX_MAP_FACES);
00878 numleaffaces = Q2_CopyLump (LUMP_LEAFFACES, dleaffaces, sizeof(dleaffaces[0]), MAX_MAP_LEAFFACES);
00879 numleafbrushes = Q2_CopyLump (LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0]), MAX_MAP_LEAFBRUSHES);
00880 numsurfedges = Q2_CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0]), MAX_MAP_SURFEDGES);
00881 numedges = Q2_CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t), MAX_MAP_EDGES);
00882 numbrushes = Q2_CopyLump (LUMP_BRUSHES, dbrushes, sizeof(dbrush_t), MAX_MAP_BRUSHES);
00883 numbrushsides = Q2_CopyLump (LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t), MAX_MAP_BRUSHSIDES);
00884 numareas = Q2_CopyLump (LUMP_AREAS, dareas, sizeof(darea_t), MAX_MAP_AREAS);
00885 numareaportals = Q2_CopyLump (LUMP_AREAPORTALS, dareaportals, sizeof(dareaportal_t), MAX_MAP_AREAPORTALS);
00886
00887 visdatasize = Q2_CopyLump (LUMP_VISIBILITY, dvisdata, 1, MAX_MAP_VISIBILITY);
00888 lightdatasize = Q2_CopyLump (LUMP_LIGHTING, dlightdata, 1, MAX_MAP_LIGHTING);
00889 entdatasize = Q2_CopyLump (LUMP_ENTITIES, dentdata, 1, MAX_MAP_ENTSTRING);
00890
00891 Q2_CopyLump (LUMP_POP, dpop, 1, MAX_MAP_DPOP);
00892
00893 FreeMemory(header);
00894
00895
00896
00897
00898 Q2_SwapBSPFile (false);
00899
00900 Q2_FixTextureReferences();
00901 }
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911 void Q2_LoadBSPFileTexinfo (char *filename)
00912 {
00913 int i;
00914 FILE *f;
00915 int length, ofs;
00916
00917 header = GetMemory(sizeof(dheader_t));
00918
00919 f = fopen (filename, "rb");
00920 fread (header, sizeof(dheader_t), 1, f);
00921
00922
00923 for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
00924 ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
00925
00926 if (header->ident != IDBSPHEADER)
00927 Error ("%s is not a IBSP file", filename);
00928 if (header->version != BSPVERSION)
00929 Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
00930
00931
00932 length = header->lumps[LUMP_TEXINFO].filelen;
00933 ofs = header->lumps[LUMP_TEXINFO].fileofs;
00934
00935 fseek (f, ofs, SEEK_SET);
00936 fread (texinfo, length, 1, f);
00937 fclose (f);
00938
00939 numtexinfo = length / sizeof(texinfo_t);
00940
00941 FreeMemory(header);
00942
00943 Q2_SwapBSPFile (false);
00944 }
00945
00946
00947
00948
00949 FILE *wadfile;
00950 dheader_t outheader;
00951
00952 void Q2_AddLump (int lumpnum, void *data, int len)
00953 {
00954 lump_t *lump;
00955
00956 lump = &header->lumps[lumpnum];
00957
00958 lump->fileofs = LittleLong( ftell(wadfile) );
00959 lump->filelen = LittleLong(len);
00960 SafeWrite (wadfile, data, (len+3)&~3);
00961 }
00962
00963
00964
00965
00966
00967
00968
00969
00970 void Q2_WriteBSPFile (char *filename)
00971 {
00972 header = &outheader;
00973 memset (header, 0, sizeof(dheader_t));
00974
00975 Q2_SwapBSPFile (true);
00976
00977 header->ident = LittleLong (IDBSPHEADER);
00978 header->version = LittleLong (BSPVERSION);
00979
00980 wadfile = SafeOpenWrite (filename);
00981 SafeWrite (wadfile, header, sizeof(dheader_t));
00982
00983 Q2_AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t));
00984 Q2_AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t));
00985 Q2_AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t));
00986 Q2_AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t));
00987 Q2_AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t));
00988 Q2_AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t));
00989 Q2_AddLump (LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t));
00990 Q2_AddLump (LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t));
00991 Q2_AddLump (LUMP_LEAFFACES, dleaffaces, numleaffaces*sizeof(dleaffaces[0]));
00992 Q2_AddLump (LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0]));
00993 Q2_AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0]));
00994 Q2_AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t));
00995 Q2_AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t));
00996 Q2_AddLump (LUMP_AREAS, dareas, numareas*sizeof(darea_t));
00997 Q2_AddLump (LUMP_AREAPORTALS, dareaportals, numareaportals*sizeof(dareaportal_t));
00998
00999 Q2_AddLump (LUMP_LIGHTING, dlightdata, lightdatasize);
01000 Q2_AddLump (LUMP_VISIBILITY, dvisdata, visdatasize);
01001 Q2_AddLump (LUMP_ENTITIES, dentdata, entdatasize);
01002 Q2_AddLump (LUMP_POP, dpop, sizeof(dpop));
01003
01004 fseek (wadfile, 0, SEEK_SET);
01005 SafeWrite (wadfile, header, sizeof(dheader_t));
01006 fclose (wadfile);
01007 }
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018 void Q2_PrintBSPFileSizes (void)
01019 {
01020 if (!num_entities)
01021 Q2_ParseEntities();
01022
01023 printf ("%6i models %7i\n"
01024 ,nummodels, (int)(nummodels*sizeof(dmodel_t)));
01025 printf ("%6i brushes %7i\n"
01026 ,numbrushes, (int)(numbrushes*sizeof(dbrush_t)));
01027 printf ("%6i brushsides %7i\n"
01028 ,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t)));
01029 printf ("%6i planes %7i\n"
01030 ,numplanes, (int)(numplanes*sizeof(dplane_t)));
01031 printf ("%6i texinfo %7i\n"
01032 ,numtexinfo, (int)(numtexinfo*sizeof(texinfo_t)));
01033 printf ("%6i entdata %7i\n", num_entities, entdatasize);
01034
01035 printf ("\n");
01036
01037 printf ("%6i vertexes %7i\n"
01038 ,numvertexes, (int)(numvertexes*sizeof(dvertex_t)));
01039 printf ("%6i nodes %7i\n"
01040 ,numnodes, (int)(numnodes*sizeof(dnode_t)));
01041 printf ("%6i faces %7i\n"
01042 ,numfaces, (int)(numfaces*sizeof(dface_t)));
01043 printf ("%6i leafs %7i\n"
01044 ,numleafs, (int)(numleafs*sizeof(dleaf_t)));
01045 printf ("%6i leaffaces %7i\n"
01046 ,numleaffaces, (int)(numleaffaces*sizeof(dleaffaces[0])));
01047 printf ("%6i leafbrushes %7i\n"
01048 ,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0])));
01049 printf ("%6i surfedges %7i\n"
01050 ,numsurfedges, (int)(numsurfedges*sizeof(dsurfedges[0])));
01051 printf ("%6i edges %7i\n"
01052 ,numedges, (int)(numedges*sizeof(dedge_t)));
01053
01054 printf ("%6i areas %7i\n"
01055 ,numareas, (int)(numareas*sizeof(darea_t)));
01056 printf ("%6i areaportals %7i\n"
01057 ,numareaportals, (int)(numareaportals*sizeof(dareaportal_t)));
01058
01059 printf (" lightdata %7i\n", lightdatasize);
01060 printf (" visdata %7i\n", visdatasize);
01061 }
01062
01063
01064
01065
01066
01067
01068
01069
01070 void Q2_ParseEntities (void)
01071 {
01072 script_t *script;
01073
01074 num_entities = 0;
01075 script = LoadScriptMemory(dentdata, entdatasize, "*Quake2 bsp file");
01076 SetScriptFlags(script, SCFL_NOSTRINGWHITESPACES |
01077 SCFL_NOSTRINGESCAPECHARS);
01078
01079 while(ParseEntity(script))
01080 {
01081 }
01082
01083 FreeScript(script);
01084 }
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094 void Q2_UnparseEntities (void)
01095 {
01096 char *buf, *end;
01097 epair_t *ep;
01098 char line[2048];
01099 int i;
01100 char key[1024], value[1024];
01101
01102 buf = dentdata;
01103 end = buf;
01104 *end = 0;
01105
01106 for (i=0 ; i<num_entities ; i++)
01107 {
01108 ep = entities[i].epairs;
01109 if (!ep)
01110 continue;
01111
01112 strcat (end,"{\n");
01113 end += 2;
01114
01115 for (ep = entities[i].epairs ; ep ; ep=ep->next)
01116 {
01117 strcpy (key, ep->key);
01118 StripTrailing (key);
01119 strcpy (value, ep->value);
01120 StripTrailing (value);
01121
01122 sprintf (line, "\"%s\" \"%s\"\n", key, value);
01123 strcat (end, line);
01124 end += strlen(line);
01125 }
01126 strcat (end,"}\n");
01127 end += 2;
01128
01129 if (end > buf + MAX_MAP_ENTSTRING)
01130 Error ("Entity text too long");
01131 }
01132 entdatasize = end - buf + 1;
01133 }
01134