Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

bspc.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 #if defined(WIN32) || defined(_WIN32)
00024 #include <direct.h>
00025 #include <windows.h>
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #else
00029 #include <unistd.h>
00030 #include <glob.h>
00031 #include <sys/stat.h>
00032 #include <unistd.h>
00033 #endif
00034 #include "qbsp.h"
00035 #include "l_mem.h"
00036 #include "../botlib/aasfile.h"
00037 #include "../botlib/be_aas_cluster.h"
00038 #include "../botlib/be_aas_optimize.h"
00039 #include "aas_create.h"
00040 #include "aas_store.h"
00041 #include "aas_file.h"
00042 #include "aas_cfg.h"
00043 #include "be_aas_bspc.h"
00044 
00045 extern  int use_nodequeue;      //brushbsp.c
00046 extern  int calcgrapplereach;   //be_aas_reach.c
00047 
00048 float           subdivide_size = 240;
00049 char            source[1024];
00050 char            name[1024];
00051 vec_t           microvolume = 1.0;
00052 char            outbase[32];
00053 int             entity_num;
00054 aas_settings_t  aassettings;
00055 
00056 qboolean    noprune;            //don't prune nodes (bspc.c)
00057 qboolean    glview;             //create a gl view
00058 qboolean    nodetail;           //don't use detail brushes (map.c)
00059 qboolean    fulldetail;         //use but don't mark detail brushes (map.c)
00060 qboolean    onlyents;           //only process the entities (bspc.c)
00061 qboolean    nomerge;            //don't merge bsp node faces (faces.c)
00062 qboolean    nowater;            //don't use the water brushes (map.c)
00063 qboolean    nocsg;              //don't carve intersecting brushes (bspc.c)
00064 qboolean    noweld;             //use unique face vertexes (faces.c)
00065 qboolean    noshare;            //don't share bsp edges (faces.c)
00066 qboolean    nosubdiv;           //don't subdivide bsp node faces (faces.c)
00067 qboolean    notjunc;            //don't create tjunctions (edge melting) (faces.c)
00068 qboolean    optimize;           //enable optimisation
00069 qboolean    leaktest;           //perform a leak test
00070 qboolean    verboseentities;
00071 qboolean    freetree;           //free the bsp tree when not needed anymore
00072 qboolean    create_aas;         //create an .AAS file
00073 qboolean    nobrushmerge;       //don't merge brushes
00074 qboolean    lessbrushes;        //create less brushes instead of correct texture placement
00075 qboolean    cancelconversion;   //true if the conversion is being cancelled
00076 qboolean    noliquids;          //no liquids when writing map file
00077 qboolean    forcesidesvisible;  //force all brush sides to be visible when loaded from bsp
00078 qboolean    capsule_collision = 0;
00079 
00080 /*
00081 //===========================================================================
00082 //
00083 // Parameter:           -
00084 // Returns:             -
00085 // Changes Globals:     -
00086 //===========================================================================
00087 void ProcessWorldModel (void)
00088 {
00089     entity_t    *e;
00090     tree_t *tree;
00091     qboolean    leaked;
00092     int brush_start, brush_end;
00093 
00094     e = &entities[entity_num];
00095 
00096     brush_start = e->firstbrush;
00097     brush_end = brush_start + e->numbrushes;
00098     leaked = false;
00099 
00100     //process the whole world in one time
00101     tree = ProcessWorldBrushes(brush_start, brush_end);
00102     //create the bsp tree portals
00103     MakeTreePortals(tree);
00104     //mark all leafs that can be reached by entities
00105     if (FloodEntities(tree))
00106     {
00107         FillOutside(tree->headnode);
00108     } //end if
00109     else
00110     {
00111         Log_Print("**** leaked ****\n");
00112         leaked = true;
00113         LeakFile(tree);
00114         if (leaktest)
00115         {
00116             Log_Print("--- MAP LEAKED ---\n");
00117             exit(0);
00118         } //end if
00119     } //end else
00120 
00121     MarkVisibleSides (tree, brush_start, brush_end);
00122 
00123     FloodAreas (tree);
00124 
00125 #ifndef ME
00126     if (glview) WriteGLView(tree, source);
00127 #endif
00128     MakeFaces(tree->headnode);
00129     FixTjuncs(tree->headnode);
00130 
00131     //NOTE: Never prune the nodes because the portals
00132     //      are screwed when prunning is done and as
00133     //      a result portal writing will crash
00134     //if (!noprune) PruneNodes(tree->headnode);
00135 
00136     WriteBSP(tree->headnode);
00137 
00138     if (!leaked) WritePortalFile(tree);
00139 
00140     Tree_Free(tree);
00141 } //end of the function ProcessWorldModel
00142 //===========================================================================
00143 //
00144 // Parameter:           -
00145 // Returns:             -
00146 // Changes Globals:     -
00147 //===========================================================================
00148 void ProcessSubModel (void)
00149 {
00150     entity_t    *e;
00151     int start, end;
00152     tree_t *tree;
00153     bspbrush_t *list;
00154     vec3_t mins, maxs;
00155 
00156     e = &entities[entity_num];
00157 
00158     start = e->firstbrush;
00159     end = start + e->numbrushes;
00160 
00161     mins[0] = mins[1] = mins[2] = -4096;
00162     maxs[0] = maxs[1] = maxs[2] = 4096;
00163     list = MakeBspBrushList(start, end, mins, maxs);
00164     if (!nocsg) list = ChopBrushes (list);
00165     tree = BrushBSP (list, mins, maxs);
00166     MakeTreePortals (tree);
00167     MarkVisibleSides (tree, start, end);
00168     MakeFaces (tree->headnode);
00169     FixTjuncs (tree->headnode);
00170     WriteBSP (tree->headnode);
00171     Tree_Free(tree);
00172 } //end of the function ProcessSubModel
00173 //===========================================================================
00174 //
00175 // Parameter:           -
00176 // Returns:             -
00177 // Changes Globals:     -
00178 //===========================================================================
00179 void ProcessModels (void)
00180 {
00181     BeginBSPFile();
00182 
00183     for (entity_num = 0; entity_num < num_entities; entity_num++)
00184     {
00185         if (!entities[entity_num].numbrushes)
00186             continue;
00187 
00188         Log_Print("############### model %i ###############\n", nummodels);
00189         BeginModel();
00190         if (entity_num == 0) ProcessWorldModel();
00191         else ProcessSubModel();
00192         EndModel();
00193 
00194         if (!verboseentities)
00195             verbose = false;    // don't bother printing submodels
00196     } //end for
00197     EndBSPFile();
00198 } //end of the function ProcessModels
00199 //===========================================================================
00200 //
00201 // Parameter:           -
00202 // Returns:             -
00203 // Changes Globals:     -
00204 //===========================================================================
00205 void Win_Map2Bsp(char *bspfilename)
00206 {
00207     double start, end;
00208     char path[1024];
00209 
00210     start = I_FloatTime();
00211 
00212     ThreadSetDefault();
00213     //yeah sure Carmack
00214     //numthreads = 1;       // multiple threads aren't helping...
00215 
00216     strcpy(source, ExpandArg(bspfilename));
00217     StripExtension(source);
00218 
00219     //delete portal and line files
00220     sprintf(path, "%s.prt", source);
00221     remove(path);
00222     sprintf(path, "%s.lin", source);
00223     remove(path);
00224 
00225     strcpy(name, ExpandArg(bspfilename));   
00226     DefaultExtension(name, ".map"); // might be .reg
00227 
00228     Q2_AllocMaxBSP();
00229     //
00230     SetModelNumbers();
00231     SetLightStyles();
00232     ProcessModels();
00233     //write the BSP
00234     Q2_WriteBSPFile(bspfilename);
00235 
00236     Q2_FreeMaxBSP();
00237 
00238     end = I_FloatTime();
00239     Log_Print("%5.0f seconds elapsed\n", end-start);
00240 } //end of the function Win_Map2Bsp
00241 //===========================================================================
00242 //
00243 // Parameter:           -
00244 // Returns:             -
00245 // Changes Globals:     -
00246 //===========================================================================
00247 void Map2Bsp(char *mapfilename, char *outputfilename)
00248 {
00249     double start, end;
00250     char path[1024];
00251 
00252     start = I_FloatTime ();
00253 
00254     ThreadSetDefault ();
00255     //yeah sure Carmack
00256     //numthreads = 1;       //multiple threads aren't helping...
00257     //SetQdirFromPath(bspfilename);
00258 
00259     strcpy(source, ExpandArg(mapfilename));
00260     StripExtension(source);
00261 
00262     // delete portal and line files
00263     sprintf(path, "%s.prt", source);
00264     remove(path);
00265     sprintf(path, "%s.lin", source);
00266     remove(path);
00267 
00268     strcpy(name, ExpandArg(mapfilename));
00269     DefaultExtension(name, ".map"); // might be .reg
00270 
00271     //
00272     // if onlyents, just grab the entites and resave
00273     //
00274     if (onlyents)
00275     {
00276         char out[1024];
00277 
00278         Q2_AllocMaxBSP();
00279         sprintf (out, "%s.bsp", source);
00280         Q2_LoadBSPFile(out, 0, 0);
00281         num_entities = 0;
00282 
00283         Q2_LoadMapFile(name);
00284         SetModelNumbers();
00285         SetLightStyles();
00286 
00287         Q2_UnparseEntities();
00288 
00289         Q2_WriteBSPFile(out);
00290         //
00291         Q2_FreeMaxBSP();
00292     } //end if
00293     else
00294     {
00295         //
00296         // start from scratch
00297         //
00298         Q2_AllocMaxBSP();
00299         //load the map
00300         Q2_LoadMapFile(name);
00301         //create the .bsp file
00302         SetModelNumbers();
00303         SetLightStyles();
00304         ProcessModels();
00305         //write the BSP
00306         Q2_WriteBSPFile(outputfilename);
00307         //
00308         Q2_FreeMaxBSP();
00309     } //end else
00310 
00311     end = I_FloatTime();
00312     Log_Print("%5.0f seconds elapsed\n", end-start);
00313 } //end of the function Map2Bsp
00314 */
00315 //===========================================================================
00316 //
00317 // Parameter:           -
00318 // Returns:             -
00319 // Changes Globals:     -
00320 //===========================================================================
00321 void AASOuputFile(quakefile_t *qf, char *outputpath, char *filename)
00322 {
00323     char ext[MAX_PATH];
00324 
00325     //
00326     if (strlen(outputpath))
00327     {
00328         strcpy(filename, outputpath);
00329         //append the bsp file base
00330         AppendPathSeperator(filename, MAX_PATH);
00331         ExtractFileBase(qf->origname, &filename[strlen(filename)]);
00332         //append .aas
00333         strcat(filename, ".aas");
00334         return;
00335     } //end if
00336     //
00337     ExtractFileExtension(qf->filename, ext);
00338     if (!stricmp(ext, "pk3") || !stricmp(ext, "pak") || !stricmp(ext, "sin"))
00339     {
00340         strcpy(filename, qf->filename);
00341         while(strlen(filename) &&
00342                 filename[strlen(filename)-1] != '\\' &&
00343                 filename[strlen(filename)-1] != '/')
00344         {
00345             filename[strlen(filename)-1] = '\0';
00346         } //end while
00347         strcat(filename, "maps");
00348         if (access(filename, 0x04)) CreatePath(filename);
00349         //append the bsp file base
00350         AppendPathSeperator(filename, MAX_PATH);
00351         ExtractFileBase(qf->origname, &filename[strlen(filename)]);
00352         //append .aas
00353         strcat(filename, ".aas");
00354     } //end if
00355     else
00356     {
00357         strcpy(filename, qf->filename);
00358         while(strlen(filename) &&
00359                 filename[strlen(filename)-1] != '.')
00360         {
00361             filename[strlen(filename)-1] = '\0';
00362         } //end while
00363         strcat(filename, "aas");
00364     } //end else
00365 } //end of the function AASOutputFile
00366 //===========================================================================
00367 //
00368 // Parameter:           -
00369 // Returns:             -
00370 // Changes Globals:     -
00371 //===========================================================================
00372 void CreateAASFilesForAllBSPFiles(char *quakepath)
00373 {
00374 #if defined(WIN32)|defined(_WIN32)
00375     WIN32_FIND_DATA filedata;
00376     HWND handle;
00377     struct _stat statbuf;
00378 #else
00379     glob_t globbuf;
00380     struct stat statbuf;
00381     int j;
00382 #endif
00383     int done;
00384     char filter[_MAX_PATH], bspfilter[_MAX_PATH], aasfilter[_MAX_PATH];
00385     char aasfile[_MAX_PATH], buf[_MAX_PATH], foldername[_MAX_PATH];
00386     quakefile_t *qf, *qf2, *files, *bspfiles, *aasfiles;
00387 
00388     strcpy(filter, quakepath);
00389     AppendPathSeperator(filter, sizeof(filter));
00390     strcat(filter, "*");
00391 
00392 #if defined(WIN32)|defined(_WIN32)
00393     handle = FindFirstFile(filter, &filedata);
00394     done = (handle == INVALID_HANDLE_VALUE);
00395     while(!done)
00396     {
00397         _splitpath(filter, foldername, NULL, NULL, NULL);
00398         _splitpath(filter, NULL, &foldername[strlen(foldername)], NULL, NULL);
00399         AppendPathSeperator(foldername, _MAX_PATH);
00400         strcat(foldername, filedata.cFileName);
00401         _stat(foldername, &statbuf);
00402 #else
00403     glob(filter, 0, NULL, &globbuf);
00404     for (j = 0; j < globbuf.gl_pathc; j++)
00405     {
00406         strcpy(foldername, globbuf.gl_pathv[j]);
00407         stat(foldername, &statbuf);
00408 #endif
00409         //if it is a folder
00410         if (statbuf.st_mode & S_IFDIR)
00411         {
00412             //
00413             AppendPathSeperator(foldername, sizeof(foldername));
00414             //get all the bsp files
00415             strcpy(bspfilter, foldername);
00416             strcat(bspfilter, "maps/*.bsp");
00417             files = FindQuakeFiles(bspfilter);
00418             strcpy(bspfilter, foldername);
00419             strcat(bspfilter, "*.pk3/maps/*.bsp");
00420             bspfiles = FindQuakeFiles(bspfilter);
00421             for (qf = bspfiles; qf; qf = qf->next) if (!qf->next) break;
00422             if (qf) qf->next = files;
00423             else bspfiles = files;
00424             //get all the aas files
00425             strcpy(aasfilter, foldername);
00426             strcat(aasfilter, "maps/*.aas");
00427             files = FindQuakeFiles(aasfilter);
00428             strcpy(aasfilter, foldername);
00429             strcat(aasfilter, "*.pk3/maps/*.aas");
00430             aasfiles = FindQuakeFiles(aasfilter);
00431             for (qf = aasfiles; qf; qf = qf->next) if (!qf->next) break;
00432             if (qf) qf->next = files;
00433             else aasfiles = files;
00434             //
00435             for (qf = bspfiles; qf; qf = qf->next)
00436             {
00437                 sprintf(aasfile, "%s/%s", qf->pakfile, qf->origname);
00438                 Log_Print("found %s\n", aasfile);
00439                 strcpy(&aasfile[strlen(aasfile)-strlen(".bsp")], ".aas");
00440                 for (qf2 = aasfiles; qf2; qf2 = qf2->next)
00441                 {
00442                     sprintf(buf, "%s/%s", qf2->pakfile, qf2->origname);
00443                     if (!stricmp(aasfile, buf))
00444                     {
00445                         Log_Print("found %s\n", buf);
00446                         break;
00447                     } //end if
00448                 } //end for
00449             } //end for
00450         } //end if
00451 #if defined(WIN32)|defined(_WIN32)
00452         //find the next file
00453         done = !FindNextFile(handle, &filedata);
00454     } //end while
00455 #else
00456     } //end for
00457     globfree(&globbuf);
00458 #endif
00459 } //end of the function CreateAASFilesForAllBSPFiles
00460 //===========================================================================
00461 //
00462 // Parameter:           -
00463 // Returns:             -
00464 // Changes Globals:     -
00465 //===========================================================================
00466 quakefile_t *GetArgumentFiles(int argc, char *argv[], int *i, char *ext)
00467 {
00468     quakefile_t *qfiles, *lastqf, *qf;
00469     int j;
00470     char buf[1024];
00471 
00472     qfiles = NULL;
00473     lastqf = NULL;
00474     for (; (*i)+1 < argc && argv[(*i)+1][0] != '-'; (*i)++)
00475     {
00476         strcpy(buf, argv[(*i)+1]);
00477         for (j = strlen(buf)-1; j >= strlen(buf)-4; j--)
00478             if (buf[j] == '.') break;
00479         if (j >= strlen(buf)-4)
00480             strcpy(&buf[j+1], ext);
00481         qf = FindQuakeFiles(buf);
00482         if (!qf) continue;
00483         if (lastqf) lastqf->next = qf;
00484         else qfiles = qf;
00485         lastqf = qf;
00486         while(lastqf->next) lastqf = lastqf->next;
00487     } //end for
00488     return qfiles;
00489 } //end of the function GetArgumentFiles
00490 //===========================================================================
00491 //
00492 // Parameter:           -
00493 // Returns:             -
00494 // Changes Globals:     -
00495 //===========================================================================
00496 
00497 #define COMP_BSP2MAP        1
00498 #define COMP_BSP2AAS        2
00499 #define COMP_REACH          3
00500 #define COMP_CLUSTER        4
00501 #define COMP_AASOPTIMIZE    5
00502 #define COMP_AASINFO        6
00503 
00504 int main (int argc, char **argv)
00505 {
00506     int i, comp = 0;
00507     char outputpath[MAX_PATH] = "";
00508     char filename[MAX_PATH] = "unknown";
00509     quakefile_t *qfiles, *qf;
00510     double start_time;
00511 
00512     myargc = argc;
00513     myargv = argv;
00514 
00515     start_time = I_FloatTime();
00516 
00517     Log_Open("bspc.log");       //open a log file
00518     Log_Print("BSPC version "BSPC_VERSION", %s %s\n", __DATE__, __TIME__);
00519 
00520     DefaultCfg();
00521     for (i = 1; i < argc; i++)
00522     {
00523         if (!stricmp(argv[i],"-threads"))
00524         {
00525             if (i + 1 >= argc) {i = 0; break;}
00526             numthreads = atoi(argv[++i]);
00527             Log_Print("threads = %d\n", numthreads);
00528         } //end if
00529         else if (!stricmp(argv[i], "-noverbose"))
00530         {
00531             Log_Print("verbose = false\n");
00532             verbose = false;
00533         } //end else if
00534         else if (!stricmp(argv[i], "-nocsg"))
00535         {
00536             Log_Print("nocsg = true\n");
00537             nocsg = true;
00538         } //end else if
00539         else if (!stricmp(argv[i], "-optimize"))
00540         {
00541             Log_Print("optimize = true\n");
00542             optimize = true;
00543         } //end else if
00544         /*
00545         else if (!stricmp(argv[i],"-glview"))
00546         {
00547             glview = true;
00548         } //end else if
00549         else if (!stricmp(argv[i], "-draw"))
00550         {
00551             Log_Print("drawflag = true\n");
00552             drawflag = true;
00553         } //end else if
00554         else if (!stricmp(argv[i], "-noweld"))
00555         {
00556             Log_Print("noweld = true\n");
00557             noweld = true;
00558         } //end else if
00559         else if (!stricmp(argv[i], "-noshare"))
00560         {
00561             Log_Print("noshare = true\n");
00562             noshare = true;
00563         } //end else if
00564         else if (!stricmp(argv[i], "-notjunc"))
00565         {
00566             Log_Print("notjunc = true\n");
00567             notjunc = true;
00568         } //end else if
00569         else if (!stricmp(argv[i], "-nowater"))
00570         {
00571             Log_Print("nowater = true\n");
00572             nowater = true;
00573         } //end else if
00574         else if (!stricmp(argv[i], "-noprune"))
00575         {
00576             Log_Print("noprune = true\n");
00577             noprune = true;
00578         } //end else if
00579         else if (!stricmp(argv[i], "-nomerge"))
00580         {
00581             Log_Print("nomerge = true\n");
00582             nomerge = true;
00583         } //end else if
00584         else if (!stricmp(argv[i], "-nosubdiv"))
00585         {
00586             Log_Print("nosubdiv = true\n");
00587             nosubdiv = true;
00588         } //end else if
00589         else if (!stricmp(argv[i], "-nodetail"))
00590         {
00591             Log_Print("nodetail = true\n");
00592             nodetail = true;
00593         } //end else if
00594         else if (!stricmp(argv[i], "-fulldetail"))
00595         {
00596             Log_Print("fulldetail = true\n");
00597             fulldetail = true;
00598         } //end else if
00599         else if (!stricmp(argv[i], "-onlyents"))
00600         {
00601             Log_Print("onlyents = true\n");
00602             onlyents = true;
00603         } //end else if
00604         else if (!stricmp(argv[i], "-micro"))
00605         {
00606             if (i + 1 >= argc) {i = 0; break;}
00607             microvolume = atof(argv[++i]);
00608             Log_Print("microvolume = %f\n", microvolume);
00609         } //end else if
00610         else if (!stricmp(argv[i], "-leaktest"))
00611         {
00612             Log_Print("leaktest = true\n");
00613             leaktest = true;
00614         } //end else if
00615         else if (!stricmp(argv[i], "-verboseentities"))
00616         {
00617             Log_Print("verboseentities = true\n");
00618             verboseentities = true;
00619         } //end else if
00620         else if (!stricmp(argv[i], "-chop"))
00621         {
00622             if (i + 1 >= argc) {i = 0; break;}
00623             subdivide_size = atof(argv[++i]);
00624             Log_Print("subdivide_size = %f\n", subdivide_size);
00625         } //end else if
00626         else if (!stricmp (argv[i], "-tmpout"))
00627         {
00628             strcpy (outbase, "/tmp");
00629             Log_Print("temp output\n");
00630         } //end else if
00631         */
00632 #ifdef ME
00633         else if (!stricmp(argv[i], "-freetree"))
00634         {
00635             freetree = true;
00636             Log_Print("freetree = true\n");
00637         } //end else if
00638         else if (!stricmp(argv[i], "-grapplereach"))
00639         {
00640             calcgrapplereach = true;
00641             Log_Print("grapplereach = true\n");
00642         } //end else if
00643         else if (!stricmp(argv[i], "-nobrushmerge"))
00644         {
00645             nobrushmerge = true;
00646             Log_Print("nobrushmerge = true\n");
00647         } //end else if
00648         else if (!stricmp(argv[i], "-noliquids"))
00649         {
00650             noliquids = true;
00651             Log_Print("noliquids = true\n");
00652         } //end else if
00653         else if (!stricmp(argv[i], "-forcesidesvisible"))
00654         {
00655             forcesidesvisible = true;
00656             Log_Print("forcesidesvisible = true\n");
00657         } //end else if
00658         else if (!stricmp(argv[i], "-output"))
00659         {
00660             if (i + 1 >= argc) {i = 0; break;}
00661             if (access(argv[i+1], 0x04)) Warning("the folder %s does not exist", argv[i+1]);
00662             strcpy(outputpath, argv[++i]);
00663         } //end else if
00664         else if (!stricmp(argv[i], "-breadthfirst"))
00665         {
00666             use_nodequeue = true;
00667             Log_Print("breadthfirst = true\n");
00668         } //end else if
00669         else if (!stricmp(argv[i], "-capsule"))
00670         {
00671             capsule_collision = true;
00672             Log_Print("capsule_collision = true\n");
00673         } //end else if
00674         else if (!stricmp(argv[i], "-cfg"))
00675         {
00676             if (i + 1 >= argc) {i = 0; break;}
00677             if (!LoadCfgFile(argv[++i]))
00678                 exit(0);
00679         } //end else if
00680         else if (!stricmp(argv[i], "-bsp2map"))
00681         {
00682             if (i + 1 >= argc) {i = 0; break;}
00683             comp = COMP_BSP2MAP;
00684             qfiles = GetArgumentFiles(argc, argv, &i, "bsp");
00685         } //end else if
00686         else if (!stricmp(argv[i], "-bsp2aas"))
00687         {
00688             if (i + 1 >= argc) {i = 0; break;}
00689             comp = COMP_BSP2AAS;
00690             qfiles = GetArgumentFiles(argc, argv, &i, "bsp");
00691         } //end else if
00692         else if (!stricmp(argv[i], "-aasall"))
00693         {
00694             if (i + 1 >= argc) {i = 0; break;}
00695             CreateAASFilesForAllBSPFiles(argv[++i]);
00696         } //end else if
00697         else if (!stricmp(argv[i], "-reach"))
00698         {
00699             if (i + 1 >= argc) {i = 0; break;}
00700             comp = COMP_REACH;
00701             qfiles = GetArgumentFiles(argc, argv, &i, "bsp");
00702         } //end else if
00703         else if (!stricmp(argv[i], "-cluster"))
00704         {
00705             if (i + 1 >= argc) {i = 0; break;}
00706             comp = COMP_CLUSTER;
00707             qfiles = GetArgumentFiles(argc, argv, &i, "bsp");
00708         } //end else if
00709         else if (!stricmp(argv[i], "-aasinfo"))
00710         {
00711             if (i + 1 >= argc) {i = 0; break;}
00712             comp = COMP_AASINFO;
00713             qfiles = GetArgumentFiles(argc, argv, &i, "aas");
00714         } //end else if
00715         else if (!stricmp(argv[i], "-aasopt"))
00716         {
00717             if (i + 1 >= argc) {i = 0; break;}
00718             comp = COMP_AASOPTIMIZE;
00719             qfiles = GetArgumentFiles(argc, argv, &i, "aas");
00720         } //end else if
00721 #endif //ME
00722         else
00723         {
00724             Log_Print("unknown parameter %s\n", argv[i]);
00725             break;
00726         } //end else
00727     } //end for
00728 
00729     //if there are parameters and there's no mismatch in one of the parameters
00730     if (argc > 1 && i == argc)
00731     {
00732         switch(comp)
00733         {
00734             case COMP_BSP2MAP:
00735             {
00736                 if (!qfiles) Log_Print("no files found\n");
00737                 for (qf = qfiles; qf; qf = qf->next)
00738                 {
00739                     //copy the output path
00740                     strcpy(filename, outputpath);
00741                     //append the bsp file base
00742                     AppendPathSeperator(filename, MAX_PATH);
00743                     ExtractFileBase(qf->origname, &filename[strlen(filename)]);
00744                     //append .map
00745                     strcat(filename, ".map");
00746                     //
00747                     Log_Print("bsp2map: %s to %s\n", qf->origname, filename);
00748                     if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname);
00749                     //
00750                     LoadMapFromBSP(qf);
00751                     //write the map file
00752                     WriteMapFile(filename);
00753                 } //end for
00754                 break;
00755             } //end case
00756             case COMP_BSP2AAS:
00757             {
00758                 if (!qfiles) Log_Print("no files found\n");
00759                 for (qf = qfiles; qf; qf = qf->next)
00760                 {
00761                     AASOuputFile(qf, outputpath, filename);
00762                     //
00763                     Log_Print("bsp2aas: %s to %s\n", qf->origname, filename);
00764                     if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname);
00765                     //set before map loading
00766                     create_aas = 1;
00767                     LoadMapFromBSP(qf);
00768                     //create the AAS file
00769                     AAS_Create(filename);
00770                     //if it's a Quake3 map calculate the reachabilities and clusters
00771                     if (loadedmaptype == MAPTYPE_QUAKE3) AAS_CalcReachAndClusters(qf);
00772                     //
00773                     if (optimize) AAS_Optimize();
00774                     //
00775                     //write out the stored AAS file
00776                     if (!AAS_WriteAASFile(filename))
00777                     {
00778                         Error("error writing %s\n", filename);
00779                     } //end if
00780                     //deallocate memory
00781                     AAS_FreeMaxAAS();
00782                 } //end for
00783                 break;
00784             } //end case
00785             case COMP_REACH:
00786             {
00787                 if (!qfiles) Log_Print("no files found\n");
00788                 for (qf = qfiles; qf; qf = qf->next)
00789                 {
00790                     AASOuputFile(qf, outputpath, filename);
00791                     //
00792                     Log_Print("reach: %s to %s\n", qf->origname, filename);
00793                     if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname);
00794                     //if the AAS file exists in the output directory
00795                     if (!access(filename, 0x04))
00796                     {
00797                         if (!AAS_LoadAASFile(filename, 0, 0))
00798                         {
00799                             Error("error loading aas file %s\n", filename);
00800                         } //end if
00801                         //assume it's a Quake3 BSP file
00802                         loadedmaptype = MAPTYPE_QUAKE3;
00803                     } //end if
00804                     else
00805                     {
00806                         Warning("AAS file %s not found in output folder\n", filename);
00807                         Log_Print("creating %s...\n", filename);
00808                         //set before map loading
00809                         create_aas = 1;
00810                         LoadMapFromBSP(qf);
00811                         //create the AAS file
00812                         AAS_Create(filename);
00813                     } //end else
00814                     //if it's a Quake3 map calculate the reachabilities and clusters
00815                     if (loadedmaptype == MAPTYPE_QUAKE3)
00816                     {
00817                         AAS_CalcReachAndClusters(qf);
00818                     } //end if
00819                     //
00820                     if (optimize) AAS_Optimize();
00821                     //write out the stored AAS file
00822                     if (!AAS_WriteAASFile(filename))
00823                     {
00824                         Error("error writing %s\n", filename);
00825                     } //end if
00826                     //deallocate memory
00827                     AAS_FreeMaxAAS();
00828                 } //end for
00829                 break;
00830             } //end case
00831             case COMP_CLUSTER:
00832             {
00833                 if (!qfiles) Log_Print("no files found\n");
00834                 for (qf = qfiles; qf; qf = qf->next)
00835                 {
00836                     AASOuputFile(qf, outputpath, filename);
00837                     //
00838                     Log_Print("cluster: %s to %s\n", qf->origname, filename);
00839                     if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname);
00840                     //if the AAS file exists in the output directory
00841                     if (!access(filename, 0x04))
00842                     {
00843                         if (!AAS_LoadAASFile(filename, 0, 0))
00844                         {
00845                             Error("error loading aas file %s\n", filename);
00846                         } //end if
00847                         //assume it's a Quake3 BSP file
00848                         loadedmaptype = MAPTYPE_QUAKE3;
00849                         //if it's a Quake3 map calculate the clusters
00850                         if (loadedmaptype == MAPTYPE_QUAKE3)
00851                         {
00852                             aasworld.numclusters = 0;
00853                             AAS_InitBotImport();
00854                             AAS_InitClustering();
00855                         } //end if
00856                     } //end if
00857                     else
00858                     {
00859                         Warning("AAS file %s not found in output folder\n", filename);
00860                         Log_Print("creating %s...\n", filename);
00861                         //set before map loading
00862                         create_aas = 1;
00863                         LoadMapFromBSP(qf);
00864                         //create the AAS file
00865                         AAS_Create(filename);
00866                         //if it's a Quake3 map calculate the reachabilities and clusters
00867                         if (loadedmaptype == MAPTYPE_QUAKE3) AAS_CalcReachAndClusters(qf);
00868                     } //end else
00869                     //
00870                     if (optimize) AAS_Optimize();
00871                     //write out the stored AAS file
00872                     if (!AAS_WriteAASFile(filename))
00873                     {
00874                         Error("error writing %s\n", filename);
00875                     } //end if
00876                     //deallocate memory
00877                     AAS_FreeMaxAAS();
00878                 } //end for
00879                 break;
00880             } //end case
00881             case COMP_AASOPTIMIZE:
00882             {
00883                 if (!qfiles) Log_Print("no files found\n");
00884                 for (qf = qfiles; qf; qf = qf->next)
00885                 {
00886                     AASOuputFile(qf, outputpath, filename);
00887                     //
00888                     Log_Print("optimizing: %s to %s\n", qf->origname, filename);
00889                     if (qf->type != QFILETYPE_AAS) Warning("%s is probably not a AAS file\n", qf->origname);
00890                     //
00891                     AAS_InitBotImport();
00892                     //
00893                     if (!AAS_LoadAASFile(qf->filename, qf->offset, qf->length))
00894                     {
00895                         Error("error loading aas file %s\n", qf->filename);
00896                     } //end if
00897                     AAS_Optimize();
00898                     //write out the stored AAS file
00899                     if (!AAS_WriteAASFile(filename))
00900                     {
00901                         Error("error writing %s\n", filename);
00902                     } //end if
00903                     //deallocate memory
00904                     AAS_FreeMaxAAS();
00905                 } //end for
00906                 break;
00907             } //end case
00908             case COMP_AASINFO:
00909             {
00910                 if (!qfiles) Log_Print("no files found\n");
00911                 for (qf = qfiles; qf; qf = qf->next)
00912                 {
00913                     AASOuputFile(qf, outputpath, filename);
00914                     //
00915                     Log_Print("aas info for: %s\n", filename);
00916                     if (qf->type != QFILETYPE_AAS) Warning("%s is probably not a AAS file\n", qf->origname);
00917                     //
00918                     AAS_InitBotImport();
00919                     //
00920                     if (!AAS_LoadAASFile(qf->filename, qf->offset, qf->length))
00921                     {
00922                         Error("error loading aas file %s\n", qf->filename);
00923                     } //end if
00924                     AAS_ShowTotals();
00925                 } //end for
00926             } //end case
00927             default:
00928             {
00929                 Log_Print("don't know what to do\n");
00930                 break;
00931             } //end default
00932         } //end switch
00933     } //end if
00934     else
00935     {
00936         Log_Print("Usage:   bspc [-<switch> [-<switch> ...]]\n"
00937 #if defined(WIN32) || defined(_WIN32)
00938             "Example 1: bspc -bsp2aas d:\\quake3\\baseq3\\maps\\mymap?.bsp\n"
00939             "Example 2: bspc -bsp2aas d:\\quake3\\baseq3\\pak0.pk3\\maps/q3dm*.bsp\n"
00940 #else
00941             "Example 1: bspc -bsp2aas /quake3/baseq3/maps/mymap?.bsp\n"
00942             "Example 2: bspc -bsp2aas /quake3/baseq3/pak0.pk3/maps/q3dm*.bsp\n"
00943 #endif
00944             "\n"
00945             "Switches:\n"
00946             //"   bsp2map  <[pakfilter/]filter.bsp>    = convert BSP to MAP\n"
00947             //"   aasall   <quake3folder>              = create AAS files for all BSPs\n"
00948             "   bsp2aas  <[pakfilter/]filter.bsp>    = convert BSP to AAS\n"
00949             "   reach    <filter.bsp>                = compute reachability & clusters\n"
00950             "   cluster  <filter.aas>                = compute clusters\n"
00951             "   aasopt   <filter.aas>                = optimize aas file\n"
00952             "   aasinfo  <filter.aas>                = show AAS file info\n"
00953             "   output   <output path>               = set output path\n"
00954             "   threads  <X>                         = set number of threads to X\n"
00955             "   cfg      <filename>                  = use this cfg file\n"
00956             "   optimize                             = enable optimization\n"
00957             "   noverbose                            = disable verbose output\n"
00958             "   breadthfirst                         = breadth first bsp building\n"
00959             "   nobrushmerge                         = don't merge brushes\n"
00960             "   noliquids                            = don't write liquids to map\n"
00961             "   freetree                             = free the bsp tree\n"
00962             "   nocsg                                = disables brush chopping\n"
00963             "   forcesidesvisible                    = force all sides to be visible\n"
00964             "   grapplereach                         = calculate grapple reachabilities\n"
00965 
00966 /*          "   glview     = output a GL view\n"
00967             "   draw       = enables drawing\n"
00968             "   noweld     = disables weld\n"
00969             "   noshare    = disables sharing\n"
00970             "   notjunc    = disables juncs\n"
00971             "   nowater    = disables water brushes\n"
00972             "   noprune    = disables node prunes\n"
00973             "   nomerge    = disables face merging\n"
00974             "   nosubdiv   = disables subdeviding\n"
00975             "   nodetail   = disables detail brushes\n"
00976             "   fulldetail = enables full detail\n"
00977             "   onlyents   = only compile entities with bsp\n"
00978             "   micro <volume>\n"
00979             "              = sets the micro volume to the given float\n"
00980             "   leaktest   = perform a leak test\n"
00981             "   verboseentities\n"
00982             "              = enable entity verbose mode\n"
00983             "   chop <subdivide_size>\n"
00984             "              = sets the subdivide size to the given float\n"*/
00985             "\n");
00986     } //end else
00987     Log_Print("BSPC run time is %5.0f seconds\n", I_FloatTime() - start_time);
00988     Log_Close();                        //close the log file
00989     return 0;
00990 } //end of the function main
00991 

Generated on Thu Aug 25 12:37:15 2005 for Quake III Arena by  doxygen 1.3.9.1