00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "shared.h"
00027 #include "bspfile.h"
00028 #include "scriplib.h"
00029 #include "../bsp.h"
00030
00036 byte *CompressRouting (byte *dataStart, byte *destStart, int l)
00037 {
00038 int c;
00039 byte val;
00040 byte *data, *dend, *dest_p, *count_p;
00041
00042 dest_p = destStart;
00043 data = dataStart;
00044 dend = dataStart + l;
00045
00046 while (data < dend) {
00047 if (data + 1 < dend && *data == *(data + 1)) {
00048
00049 val = *data++;
00050 data++;
00051 c = 0;
00052
00053 while (data + 1 < dend && val == *(data)) {
00054 if (c >= SCHAR_MAX)
00055 break;
00056 data++;
00057 c++;
00058 }
00059 count_p = dest_p;
00060 *dest_p++ = (byte)(c) | 0x80;
00061 *dest_p++ = val;
00062 } else {
00063
00064 count_p = dest_p++;
00065 c = 0;
00066 while ((data + 1 < dend && *data != *(data + 1)) || data == dend - 1) {
00067 if (c >= SCHAR_MAX)
00068 break;
00069 *dest_p++ = *data++;
00070 c++;
00071 }
00072 *count_p = (byte)c;
00073 }
00074 }
00075
00076
00077 *dest_p++ = 0;
00078
00079 return dest_p;
00080 }
00081
00085 static void SwapBSPFile (void)
00086 {
00087 int i, j, k;
00088
00089
00090 for (i = 0; i < curTile->nummodels; i++) {
00091 dBspModel_t *d = &curTile->models[i];
00092
00093 d->firstface = LittleLong(d->firstface);
00094 d->numfaces = LittleLong(d->numfaces);
00095 d->headnode = LittleLong(d->headnode);
00096
00097 for (j = 0; j < 3; j++) {
00098 d->mins[j] = LittleFloat(d->mins[j]);
00099 d->maxs[j] = LittleFloat(d->maxs[j]);
00100 d->origin[j] = LittleFloat(d->origin[j]);
00101 }
00102 }
00103
00104
00105 for (i = 0; i < curTile->numvertexes; i++) {
00106 for (j = 0; j < 3; j++)
00107 curTile->vertexes[i].point[j] = LittleFloat(curTile->vertexes[i].point[j]);
00108 }
00109
00110
00111 for (i = 0; i < curTile->numplanes; i++) {
00112 for (j = 0; j < 3; j++)
00113 curTile->planes[i].normal[j] = LittleFloat(curTile->planes[i].normal[j]);
00114 curTile->planes[i].dist = LittleFloat(curTile->planes[i].dist);
00115 curTile->planes[i].type = LittleLong(curTile->planes[i].type);
00116 }
00117
00118
00119 for (i = 0; i < curTile->numtexinfo; i++) {
00120 for (j = 0; j < 2; j++)
00121 for (k = 0; k < 4; k++)
00122 curTile->texinfo[i].vecs[j][k] = LittleFloat(curTile->texinfo[i].vecs[j][k]);
00123 curTile->texinfo[i].surfaceFlags = LittleLong(curTile->texinfo[i].surfaceFlags);
00124 curTile->texinfo[i].value = LittleLong(curTile->texinfo[i].value);
00125 }
00126
00127
00128 for (i = 0; i < curTile->numfaces; i++) {
00129 curTile->faces[i].texinfo = LittleShort(curTile->faces[i].texinfo);
00130 curTile->faces[i].planenum = LittleShort(curTile->faces[i].planenum);
00131 curTile->faces[i].side = LittleShort(curTile->faces[i].side);
00132 for (j = 0; j < LIGHTMAP_MAX; j++)
00133 curTile->faces[i].lightofs[j] = LittleLong(curTile->faces[i].lightofs[j]);
00134 curTile->faces[i].firstedge = LittleLong(curTile->faces[i].firstedge);
00135 curTile->faces[i].numedges = LittleShort(curTile->faces[i].numedges);
00136 }
00137
00138
00139 for (i = 0; i < curTile->numnodes; i++) {
00140
00141 curTile->nodes[i].planenum = LittleLong(curTile->nodes[i].planenum);
00142 for (j = 0; j < 3; j++) {
00143 curTile->nodes[i].mins[j] = LittleShort(curTile->nodes[i].mins[j]);
00144 curTile->nodes[i].maxs[j] = LittleShort(curTile->nodes[i].maxs[j]);
00145 }
00146 curTile->nodes[i].children[0] = LittleLong(curTile->nodes[i].children[0]);
00147 curTile->nodes[i].children[1] = LittleLong(curTile->nodes[i].children[1]);
00148 curTile->nodes[i].firstface = LittleShort(curTile->nodes[i].firstface);
00149 curTile->nodes[i].numfaces = LittleShort(curTile->nodes[i].numfaces);
00150 }
00151
00152
00153 for (i = 0; i < curTile->numleafs; i++) {
00154 curTile->leafs[i].contentFlags = LittleLong(curTile->leafs[i].contentFlags);
00155 curTile->leafs[i].area = LittleShort(curTile->leafs[i].area);
00156 for (j = 0; j < 3; j++) {
00157 curTile->leafs[i].mins[j] = LittleShort(curTile->leafs[i].mins[j]);
00158 curTile->leafs[i].maxs[j] = LittleShort(curTile->leafs[i].maxs[j]);
00159 }
00160
00161 curTile->leafs[i].firstleafbrush = LittleShort(curTile->leafs[i].firstleafbrush);
00162 curTile->leafs[i].numleafbrushes = LittleShort(curTile->leafs[i].numleafbrushes);
00163 }
00164
00165
00166 for (i = 0; i < curTile->numleafbrushes; i++)
00167 curTile->leafbrushes[i] = LittleShort(curTile->leafbrushes[i]);
00168
00169
00170 for (i = 0; i < curTile->numsurfedges; i++)
00171 curTile->surfedges[i] = LittleLong(curTile->surfedges[i]);
00172
00173
00174 for (i = 0; i < curTile->numedges; i++) {
00175 curTile->edges[i].v[0] = LittleShort(curTile->edges[i].v[0]);
00176 curTile->edges[i].v[1] = LittleShort(curTile->edges[i].v[1]);
00177 }
00178
00179
00180 for (i = 0; i < curTile->numbrushes; i++) {
00181 curTile->dbrushes[i].firstbrushside = LittleLong(curTile->dbrushes[i].firstbrushside);
00182 curTile->dbrushes[i].numsides = LittleLong(curTile->dbrushes[i].numsides);
00183 curTile->dbrushes[i].contentFlags = LittleLong(curTile->dbrushes[i].contentFlags);
00184 }
00185
00186
00187 for (i = 0; i < curTile->numbrushes; i++) {
00188 curTile->brushes[i].firstbrushside = LittleLong(curTile->brushes[i].firstbrushside);
00189 curTile->brushes[i].numsides = LittleLong(curTile->brushes[i].numsides);
00190 curTile->brushes[i].contentFlags = LittleLong(curTile->brushes[i].contentFlags);
00191 }
00192
00193
00194 for (i = 0; i < curTile->numbrushsides; i++) {
00195 curTile->brushsides[i].planenum = LittleShort(curTile->brushsides[i].planenum);
00196 curTile->brushsides[i].texinfo = LittleShort(curTile->brushsides[i].texinfo);
00197 }
00198 }
00199
00200
00201 static dBspHeader_t *header;
00202
00203 static int CopyLump (int lump, void *dest, int size)
00204 {
00205 const int length = header->lumps[lump].filelen;
00206 const int ofs = header->lumps[lump].fileofs;
00207
00208 if (length == 0)
00209 return 0;
00210 if (length % size)
00211 Sys_Error("LoadBSPFile: odd lump size");
00212
00213 memcpy(dest, (byte *)header + ofs, length);
00214
00215 return length / size;
00216 }
00217
00221 void LoadBSPFile (const char *filename)
00222 {
00223 int size;
00224 unsigned int i;
00225
00226
00227 curTile = &mapTiles.mapTiles[0];
00228
00229 mapTiles.numTiles = 1;
00230
00231
00232 size = FS_LoadFile(filename, (byte **)&header);
00233 if (size == -1)
00234 Sys_Error("'%s' doesn't exist", filename);
00235
00236
00237 for (i = 0; i < sizeof(dBspHeader_t) / 4; i++)
00238 ((int *)header)[i] = LittleLong(((int *)header)[i]);
00239
00240 if (header->ident != IDBSPHEADER)
00241 Sys_Error("%s is not a IBSP file", filename);
00242 if (header->version != BSPVERSION)
00243 Sys_Error("%s is version %i, not %i", filename, header->version, BSPVERSION);
00244
00245 curTile->nummodels = CopyLump(LUMP_MODELS, curTile->models, sizeof(dBspModel_t));
00246 curTile->numvertexes = CopyLump(LUMP_VERTEXES, curTile->vertexes, sizeof(dBspVertex_t));
00247 curTile->numplanes = CopyLump(LUMP_PLANES, curTile->planes, sizeof(dBspPlane_t));
00248 curTile->numleafs = CopyLump(LUMP_LEAFS, curTile->leafs, sizeof(dBspLeaf_t));
00249 curTile->numnormals = CopyLump(LUMP_NORMALS, curTile->normals, sizeof(dBspNormal_t));
00250 curTile->numnodes = CopyLump(LUMP_NODES, curTile->nodes, sizeof(dBspNode_t));
00251 curTile->numtexinfo = CopyLump(LUMP_TEXINFO, curTile->texinfo, sizeof(dBspTexinfo_t));
00252 curTile->numfaces = CopyLump(LUMP_FACES, curTile->faces, sizeof(dBspSurface_t));
00253 curTile->numleafbrushes = CopyLump(LUMP_LEAFBRUSHES, curTile->leafbrushes, sizeof(curTile->leafbrushes[0]));
00254 curTile->numsurfedges = CopyLump(LUMP_SURFEDGES, curTile->surfedges, sizeof(curTile->surfedges[0]));
00255 curTile->numedges = CopyLump(LUMP_EDGES, curTile->edges, sizeof(dBspEdge_t));
00256 curTile->numbrushes = CopyLump(LUMP_BRUSHES, curTile->dbrushes, sizeof(dBspBrush_t));
00257 curTile->numbrushsides = CopyLump(LUMP_BRUSHSIDES, curTile->brushsides, sizeof(dBspBrushSide_t));
00258 curTile->routedatasize = CopyLump(LUMP_ROUTING, curTile->routedata, 1);
00259 curTile->lightdatasize[LIGHTMAP_NIGHT] = CopyLump(LUMP_LIGHTING_NIGHT, curTile->lightdata[LIGHTMAP_NIGHT], 1);
00260 curTile->lightdatasize[LIGHTMAP_DAY] = CopyLump(LUMP_LIGHTING_DAY, curTile->lightdata[LIGHTMAP_DAY], 1);
00261 curTile->entdatasize = CopyLump(LUMP_ENTITIES, curTile->entdata, 1);
00262
00263
00264
00265 memset(curTile->brushes, 0, MAX_MAP_BRUSHES * sizeof(cBspBrush_t));
00266 for (i = 0; i < curTile->numbrushes; i++) {
00267 curTile->brushes[i].firstbrushside = curTile->dbrushes[i].firstbrushside;
00268 curTile->brushes[i].numsides = curTile->dbrushes[i].numsides;
00269 curTile->brushes[i].contentFlags = curTile->dbrushes[i].contentFlags;
00270 }
00271
00272
00273 FS_FreeFile(header);
00274
00275
00276 SwapBSPFile();
00277 }
00278
00283 static inline void AddLump (qFILE *bspfile, dBspHeader_t *header, int lumpnum, void *data, int len)
00284 {
00285 lump_t *lump;
00286
00287 lump = &header->lumps[lumpnum];
00288
00289 lump->fileofs = LittleLong(ftell(bspfile->f));
00290 lump->filelen = LittleLong(len);
00291
00292 FS_Write(data, (len + 3) &~ 3, bspfile);
00293 }
00294
00299 long WriteBSPFile (const char *filename)
00300 {
00301 qFILE bspfile;
00302 dBspHeader_t outheader;
00303 long size;
00304
00305 memset(&outheader, 0, sizeof(outheader));
00306 memset(&bspfile, 0, sizeof(bspfile));
00307
00308 SwapBSPFile();
00309
00310 outheader.ident = LittleLong(IDBSPHEADER);
00311 outheader.version = LittleLong(BSPVERSION);
00312
00313 FS_OpenFile(filename, &bspfile, FILE_WRITE);
00314 if (!bspfile.f)
00315 Sys_Error("Could not write bsp file");
00316 FS_Write(&outheader, sizeof(dBspHeader_t), &bspfile);
00317
00318 AddLump(&bspfile, &outheader, LUMP_PLANES, curTile->planes, curTile->numplanes * sizeof(dBspPlane_t));
00319 AddLump(&bspfile, &outheader, LUMP_LEAFS, curTile->leafs, curTile->numleafs * sizeof(dBspLeaf_t));
00320 AddLump(&bspfile, &outheader, LUMP_VERTEXES, curTile->vertexes, curTile->numvertexes * sizeof(dBspVertex_t));
00321 AddLump(&bspfile, &outheader, LUMP_NORMALS, curTile->normals, curTile->numnormals * sizeof(dBspNormal_t));
00322 AddLump(&bspfile, &outheader, LUMP_NODES, curTile->nodes, curTile->numnodes * sizeof(dBspNode_t));
00323 AddLump(&bspfile, &outheader, LUMP_TEXINFO, curTile->texinfo, curTile->numtexinfo * sizeof(dBspTexinfo_t));
00324 AddLump(&bspfile, &outheader, LUMP_FACES, curTile->faces, curTile->numfaces * sizeof(dBspSurface_t));
00325 AddLump(&bspfile, &outheader, LUMP_BRUSHES, curTile->dbrushes, curTile->numbrushes * sizeof(dBspBrush_t));
00326 AddLump(&bspfile, &outheader, LUMP_BRUSHSIDES, curTile->brushsides, curTile->numbrushsides * sizeof(dBspBrushSide_t));
00327 AddLump(&bspfile, &outheader, LUMP_LEAFBRUSHES, curTile->leafbrushes, curTile->numleafbrushes * sizeof(curTile->leafbrushes[0]));
00328 AddLump(&bspfile, &outheader, LUMP_SURFEDGES, curTile->surfedges, curTile->numsurfedges * sizeof(curTile->surfedges[0]));
00329 AddLump(&bspfile, &outheader, LUMP_EDGES, curTile->edges, curTile->numedges * sizeof(dBspEdge_t));
00330 AddLump(&bspfile, &outheader, LUMP_MODELS, curTile->models, curTile->nummodels * sizeof(dBspModel_t));
00331 AddLump(&bspfile, &outheader, LUMP_LIGHTING_NIGHT, curTile->lightdata[0], curTile->lightdatasize[0]);
00332 AddLump(&bspfile, &outheader, LUMP_LIGHTING_DAY, curTile->lightdata[1], curTile->lightdatasize[1]);
00333 AddLump(&bspfile, &outheader, LUMP_ROUTING, curTile->routedata, curTile->routedatasize);
00334 AddLump(&bspfile, &outheader, LUMP_ENTITIES, curTile->entdata, curTile->entdatasize);
00335 size = ftell(bspfile.f);
00336
00337 fseek(bspfile.f, 0L, SEEK_SET);
00338 FS_Write(&outheader, sizeof(outheader), &bspfile);
00339 FS_CloseFile(&bspfile);
00340
00341 SwapBSPFile();
00342
00343 return size;
00344 }
00345
00349 void PrintBSPFileSizes (void)
00350 {
00351 if (!num_entities)
00352 ParseEntities();
00353
00354 Com_Printf("amout type size in bytes\n");
00355 Com_Printf("================================\n");
00356 Com_Printf("%5i models %7i\n", curTile->nummodels, (int)(curTile->nummodels * sizeof(cBspModel_t)));
00357 Com_Printf("%5i brushes %7i\n", curTile->numbrushes, (int)(curTile->numbrushes * sizeof(dBspBrush_t)));
00358 Com_Printf("%5i brushsides %7i\n", curTile->numbrushsides, (int)(curTile->numbrushsides * sizeof(dBspBrushSide_t)));
00359 Com_Printf("%5i planes %7i\n", curTile->numplanes, (int)(curTile->numplanes * sizeof(dBspPlane_t)));
00360 Com_Printf("%5i texinfo %7i\n", curTile->numtexinfo, (int)(curTile->numtexinfo * sizeof(dBspTexinfo_t)));
00361 Com_Printf("%5i entdata %7i\n", num_entities, curTile->entdatasize);
00362
00363 Com_Printf("\n");
00364
00365 Com_Printf("%5i normales %7i\n", curTile->numnormals, (int)(curTile->numnormals * sizeof(dBspNormal_t)));
00366 Com_Printf("%5i vertexes %7i\n", curTile->numvertexes, (int)(curTile->numvertexes * sizeof(dBspVertex_t)));
00367 Com_Printf("%5i nodes %7i\n", curTile->numnodes, (int)(curTile->numnodes * sizeof(dBspNode_t)));
00368 Com_Printf("%5i faces %7i\n", curTile->numfaces, (int)(curTile->numfaces * sizeof(dBspSurface_t)));
00369 Com_Printf("%5i leafs %7i\n", curTile->numleafs, (int)(curTile->numleafs * sizeof(dBspLeaf_t)));
00370 Com_Printf("%5i leafbrushes %7i\n", curTile->numleafbrushes, (int)(curTile->numleafbrushes * sizeof(curTile->leafbrushes[0])));
00371 Com_Printf("%5i surfedges %7i\n", curTile->numsurfedges, (int)(curTile->numsurfedges * sizeof(curTile->surfedges[0])));
00372 Com_Printf("%5i edges %7i\n", curTile->numedges, (int)(curTile->numedges * sizeof(dBspEdge_t)));
00373 Com_Printf("night lightdata %7i\n", curTile->lightdatasize[0]);
00374 Com_Printf(" day lightdata %7i\n", curTile->lightdatasize[1]);
00375 Com_Printf(" routedata %7i\n", curTile->routedatasize);
00376 }
00377
00378
00379 int num_entities;
00380 entity_t entities[MAX_MAP_ENTITIES];
00381
00387 static void StripTrailingWhitespaces (char *str)
00388 {
00389 char *s;
00390
00391 s = str + strlen(str) - 1;
00392 while (s >= str && *s <= ' ') {
00393 *s = '\0';
00394 s--;
00395 }
00396 }
00397
00405 epair_t *ParseEpair (void)
00406 {
00407 epair_t *e;
00408
00409 e = Mem_Alloc(sizeof(*e));
00410
00411 if (strlen(parsedToken) >= MAX_KEY - 1)
00412 Sys_Error("ParseEpar: token too long");
00413 e->key = Mem_StrDup(parsedToken);
00414 GetToken(qfalse);
00415 if (strlen(parsedToken) >= MAX_VALUE - 1)
00416 Sys_Error("ParseEpar: token too long");
00417 e->value = Mem_StrDup(parsedToken);
00418
00419
00420 StripTrailingWhitespaces(e->key);
00421 StripTrailingWhitespaces(e->value);
00422
00423 return e;
00424 }
00425
00426
00430 static entity_t* ParseEntity (void)
00431 {
00432 entity_t *mapent;
00433
00434 if (!GetToken(qtrue))
00435 return NULL;
00436
00437 if (parsedToken[0] != '{')
00438 Sys_Error("ParseEntity: { not found");
00439
00440 if (num_entities >= MAX_MAP_ENTITIES)
00441 Sys_Error("num_entities >= MAX_MAP_ENTITIES (%i)", num_entities);
00442
00443 mapent = &entities[num_entities];
00444 num_entities++;
00445
00446 do {
00447 if (!GetToken(qtrue))
00448 Sys_Error("ParseEntity: EOF without closing brace");
00449 if (*parsedToken == '}') {
00450 break;
00451 } else {
00452 epair_t *e = ParseEpair();
00453 e->next = mapent->epairs;
00454 mapent->epairs = e;
00455 }
00456 } while (1);
00457
00458 return mapent;
00459 }
00460
00466 void ParseEntities (void)
00467 {
00468 int subdivide;
00469
00470 num_entities = 0;
00471 ParseFromMemory(curTile->entdata, curTile->entdatasize);
00472
00473 while (ParseEntity() != NULL) {
00474 }
00475
00476 subdivide = atoi(ValueForKey(&entities[0], "subdivide"));
00477 if (subdivide >= 256 && subdivide <= 2048) {
00478 Verb_Printf(VERB_EXTRA, "Using subdivide %d from worldspawn.\n", subdivide);
00479 config.subdivideSize = subdivide;
00480 }
00481 }
00482
00483
00488 const char *UnparseEntities (void)
00489 {
00490 char line[2048], key[1024], value[1024];
00491 int i;
00492
00493 curTile->entdata[0] = '\0';
00494
00495 for (i = 0; i < num_entities; i++) {
00496 const epair_t *ep = entities[i].epairs;
00497 if (!ep)
00498 continue;
00499
00500 Q_strcat(curTile->entdata, "{\n", sizeof(curTile->entdata));
00501
00502 for (ep = entities[i].epairs; ep; ep = ep->next) {
00503 Q_strncpyz(key, ep->key, sizeof(key));
00504 StripTrailingWhitespaces(key);
00505 Q_strncpyz(value, ep->value, sizeof(value));
00506 StripTrailingWhitespaces(value);
00507
00508 Com_sprintf(line, sizeof(line), "\"%s\" \"%s\"\n", key, value);
00509 Q_strcat(curTile->entdata, line, sizeof(curTile->entdata));
00510 }
00511 Q_strcat(curTile->entdata, "}\n", sizeof(curTile->entdata));
00512 }
00513 curTile->entdatasize = strlen(curTile->entdata);
00514
00515 return curTile->entdata;
00516 }
00517
00518 void SetKeyValue (entity_t *ent, const char *key, const char *value)
00519 {
00520 epair_t *ep;
00521
00522 for (ep = ent->epairs; ep; ep = ep->next)
00523 if (!strcmp(ep->key, key)) {
00524 Mem_Free(ep->value);
00525 ep->value = Mem_StrDup(value);
00526 return;
00527 }
00528 ep = Mem_Alloc(sizeof(*ep));
00529 ep->next = ent->epairs;
00530 ent->epairs = ep;
00531 ep->key = Mem_StrDup(key);
00532 ep->value = Mem_StrDup(value);
00533 }
00534
00535 const char *ValueForKey (const entity_t *ent, const char *key)
00536 {
00537 const epair_t *ep;
00538
00539 for (ep = ent->epairs; ep; ep = ep->next)
00540 if (!strcmp(ep->key, key))
00541 return ep->value;
00542 return "";
00543 }
00544
00545 vec_t FloatForKey (const entity_t *ent, const char *key)
00546 {
00547 const char *k;
00548
00549 k = ValueForKey(ent, key);
00550 return atof(k);
00551 }
00552
00556 void GetVectorFromString (const char *value, vec3_t vec)
00557 {
00558 if (value[0] != '\0') {
00559 double v1, v2, v3;
00560
00561
00562 v1 = v2 = v3 = 0;
00563 sscanf(value, "%lf %lf %lf", &v1, &v2, &v3);
00564 vec[0] = v1;
00565 vec[1] = v2;
00566 vec[2] = v3;
00567 } else
00568 VectorClear(vec);
00569 }
00570
00574 void GetVectorForKey (const entity_t *ent, const char *key, vec3_t vec)
00575 {
00576 const char *k = ValueForKey(ent, key);
00577 GetVectorFromString(k, vec);
00578 }