int main (int argc, char **argv) { int i, comp = 0; char outputpath[MAX_PATH] = ""; char filename[MAX_PATH] = "unknown"; quakefile_t *qfiles = NULL, *qf; double start_time; myargc = argc; myargv = argv; start_time = I_FloatTime(); Log_Open("bspc.log"); //open a log file Log_Print(BSPC_NAME" version "BSPC_VERSION", %s %s\n", __DATE__, __TIME__); #ifdef ZTMAUTOARGS calcgrapplereach = true; forcesidesvisible = true; // Currently always required or BSPC fails? #endif DefaultCfg(); for (i = 1; i < argc; i++) { if (!stricmp(argv[i],"-threads")) { if (i + 1 >= argc) {i = 0; break;} numthreads = atoi(argv[++i]); Log_Print("threads = %d\n", numthreads); } //end if else if (!stricmp(argv[i], "-noverbose")) { Log_Print("verbose = false\n"); verbose = false; } //end else if else if (!stricmp(argv[i], "-nocsg")) { Log_Print("nocsg = true\n"); nocsg = true; } //end else if else if (!stricmp(argv[i], "-optimize")) { Log_Print("optimize = true\n"); optimize = true; } //end else if /* else if (!stricmp(argv[i], "-noweld")) { Log_Print("noweld = true\n"); noweld = true; } //end else if else if (!stricmp(argv[i], "-noshare")) { Log_Print("noshare = true\n"); noshare = true; } //end else if else if (!stricmp(argv[i], "-notjunc")) { Log_Print("notjunc = true\n"); notjunc = true; } //end else if else if (!stricmp(argv[i], "-nowater")) { Log_Print("nowater = true\n"); nowater = true; } //end else if else if (!stricmp(argv[i], "-noprune")) { Log_Print("noprune = true\n"); noprune = true; } //end else if else if (!stricmp(argv[i], "-nomerge")) { Log_Print("nomerge = true\n"); nomerge = true; } //end else if else if (!stricmp(argv[i], "-nosubdiv")) { Log_Print("nosubdiv = true\n"); nosubdiv = true; } //end else if else if (!stricmp(argv[i], "-nodetail")) { Log_Print("nodetail = true\n"); nodetail = true; } //end else if else if (!stricmp(argv[i], "-fulldetail")) { Log_Print("fulldetail = true\n"); fulldetail = true; } //end else if else if (!stricmp(argv[i], "-onlyents")) { Log_Print("onlyents = true\n"); onlyents = true; } //end else if else if (!stricmp(argv[i], "-micro")) { if (i + 1 >= argc) {i = 0; break;} microvolume = atof(argv[++i]); Log_Print("microvolume = %f\n", microvolume); } //end else if else if (!stricmp(argv[i], "-leaktest")) { Log_Print("leaktest = true\n"); leaktest = true; } //end else if else if (!stricmp(argv[i], "-verboseentities")) { Log_Print("verboseentities = true\n"); verboseentities = true; } //end else if else if (!stricmp(argv[i], "-chop")) { if (i + 1 >= argc) {i = 0; break;} subdivide_size = atof(argv[++i]); Log_Print("subdivide_size = %f\n", subdivide_size); } //end else if else if (!stricmp (argv[i], "-tmpout")) { strcpy (outbase, "/tmp"); Log_Print("temp output\n"); } //end else if */ else if (!stricmp(argv[i], "-freetree")) { freetree = true; Log_Print("freetree = true\n"); } //end else if else if (!stricmp(argv[i], "-grapplereach")) { calcgrapplereach = true; Log_Print("grapplereach = true\n"); } //end else if #ifdef ZTMAUTOARGS else if (!stricmp(argv[i], "-nograpplereach")) { calcgrapplereach = false; Log_Print("grapplereach = false\n"); } //end else if #endif else if (!stricmp(argv[i], "-nobrushmerge")) { nobrushmerge = true; Log_Print("nobrushmerge = true\n"); } //end else if else if (!stricmp(argv[i], "-noliquids")) { noliquids = true; Log_Print("noliquids = true\n"); } //end else if else if (!stricmp(argv[i], "-forcesidesvisible")) { forcesidesvisible = true; Log_Print("forcesidesvisible = true\n"); } //end else if #ifdef ZTMAUTOARGS else if (!stricmp(argv[i], "-noforcesidesvisible")) { forcesidesvisible = false; Log_Print("forcesidesvisible = false\n"); } //end else if #endif else if (!stricmp(argv[i], "-output")) { if (i + 1 >= argc) {i = 0; break;} if (access(argv[i+1], 0x04)) Warning("the folder %s does not exist", argv[i+1]); strcpy(outputpath, argv[++i]); } //end else if else if (!stricmp(argv[i], "-breadthfirst")) { use_nodequeue = true; Log_Print("breadthfirst = true\n"); } //end else if else if (!stricmp(argv[i], "-capsule")) { capsule_collision = true; Log_Print("capsule_collision = true\n"); } //end else if else if (!stricmp(argv[i], "-cfg")) { if (i + 1 >= argc) {i = 0; break;} if (!LoadCfgFile(argv[++i])) exit(0); } //end else if else if (!stricmp(argv[i], "-bsp2map")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_BSP2MAP; qfiles = GetArgumentFiles(argc, argv, &i, "bsp"); } //end else if else if (!stricmp(argv[i], "-bsp2aas")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_BSP2AAS; qfiles = GetArgumentFiles(argc, argv, &i, "bsp"); } //end else if else if (!stricmp(argv[i], "-aasall")) { if (i + 1 >= argc) {i = 0; break;} CreateAASFilesForAllBSPFiles(argv[++i]); } //end else if else if (!stricmp(argv[i], "-reach")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_REACH; qfiles = GetArgumentFiles(argc, argv, &i, "bsp"); } //end else if else if (!stricmp(argv[i], "-cluster")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_CLUSTER; qfiles = GetArgumentFiles(argc, argv, &i, "bsp"); } //end else if else if (!stricmp(argv[i], "-aasinfo")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_AASINFO; qfiles = GetArgumentFiles(argc, argv, &i, "aas"); } //end else if else if (!stricmp(argv[i], "-aasopt")) { if (i + 1 >= argc) {i = 0; break;} comp = COMP_AASOPTIMIZE; qfiles = GetArgumentFiles(argc, argv, &i, "aas"); } //end else if else { Log_Print("unknown parameter %s\n", argv[i]); break; } //end else } //end for //if there are parameters and there's no mismatch in one of the parameters if (argc > 1 && i == argc) { switch(comp) { case COMP_BSP2MAP: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { //copy the output path strcpy(filename, outputpath); //append the bsp file base AppendPathSeperator(filename, MAX_PATH); ExtractFileBase(qf->origname, &filename[strlen(filename)]); //append .map strcat(filename, ".map"); // Log_Print("bsp2map: %s to %s\n", qf->origname, filename); if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname); // LoadMapFromBSP(qf); //write the map file WriteMapFile(filename); } //end for break; } //end case case COMP_BSP2AAS: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { AASOuputFile(qf, outputpath, filename); // Log_Print("bsp2aas: %s to %s\n", qf->origname, filename); if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname); //set before map loading create_aas = 1; LoadMapFromBSP(qf); //create the AAS file AAS_Create(filename); //calculate the reachabilities and clusters AAS_CalcReachAndClusters(qf); // if (optimize) AAS_Optimize(); // //write out the stored AAS file if (!AAS_WriteAASFile(filename)) { Error("error writing %s\n", filename); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_REACH: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { AASOuputFile(qf, outputpath, filename); // Log_Print("reach: %s to %s\n", qf->origname, filename); if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname); //if the AAS file exists in the output directory if (!access(filename, 0x04)) { if (!AAS_LoadAASFile(filename)) { Error("error loading aas file %s\n", filename); } //end if } //end if else { Warning("AAS file %s not found in output folder\n", filename); Log_Print("creating %s...\n", filename); //set before map loading create_aas = 1; LoadMapFromBSP(qf); //create the AAS file AAS_Create(filename); } //end else //calculate the reachabilities and clusters AAS_CalcReachAndClusters(qf); // if (optimize) AAS_Optimize(); //write out the stored AAS file if (!AAS_WriteAASFile(filename)) { Error("error writing %s\n", filename); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_CLUSTER: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { AASOuputFile(qf, outputpath, filename); // Log_Print("cluster: %s to %s\n", qf->origname, filename); if (qf->type != QFILETYPE_BSP) Warning("%s is probably not a BSP file\n", qf->origname); //if the AAS file exists in the output directory if (!access(filename, 0x04)) { if (!AAS_LoadAASFile(filename)) { Error("error loading aas file %s\n", filename); } //end if //calculate the clusters AAS_RecalcClusters(); } //end if else { Warning("AAS file %s not found in output folder\n", filename); Log_Print("creating %s...\n", filename); //set before map loading create_aas = 1; LoadMapFromBSP(qf); //create the AAS file AAS_Create(filename); //calculate the reachabilities and clusters AAS_CalcReachAndClusters(qf); } //end else // if (optimize) AAS_Optimize(); //write out the stored AAS file if (!AAS_WriteAASFile(filename)) { Error("error writing %s\n", filename); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_AASOPTIMIZE: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { AASOuputFile(qf, outputpath, filename); // Log_Print("optimizing: %s to %s\n", qf->origname, filename); if (qf->type != QFILETYPE_AAS) Warning("%s is probably not a AAS file\n", qf->origname); // AAS_InitBotImport(); // if (!AAS_LoadAASFile(qf->filename)) { Error("error loading aas file %s\n", qf->filename); } //end if AAS_Optimize(); //write out the stored AAS file if (!AAS_WriteAASFile(filename)) { Error("error writing %s\n", filename); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_AASINFO: { if (!qfiles) Log_Print("no files found\n"); for (qf = qfiles; qf; qf = qf->next) { AASOuputFile(qf, outputpath, filename); // Log_Print("aas info for: %s\n", filename); if (qf->type != QFILETYPE_AAS) Warning("%s is probably not a AAS file\n", qf->origname); // AAS_InitBotImport(); // if (!AAS_LoadAASFile(qf->filename)) { Error("error loading aas file %s\n", qf->filename); } //end if AAS_ShowTotals(); } //end for break; } //end case default: { Log_Print("don't know what to do\n"); break; } //end default } //end switch } //end if else { Log_Print("Usage: bspc [-<switch> [-<switch> ...]]\n" #ifdef _WIN32 "Example 1: bspc -bsp2aas d:\\quake3\\baseq3\\maps\\mymap?.bsp\n" "Example 2: bspc -bsp2aas d:\\quake3\\baseq3\\pak0.pk3\\maps/q3dm*.bsp\n" #else "Example 1: bspc -bsp2aas /quake3/baseq3/maps/mymap?.bsp\n" "Example 2: bspc -bsp2aas /quake3/baseq3/pak0.pk3/maps/q3dm*.bsp\n" #endif "\n" "Switches:\n" //" bsp2map <[pakfilter/]filter.bsp> = convert BSP to MAP\n" //" aasall <quake3folder> = create AAS files for all BSPs\n" " bsp2aas <[pakfilter/]filter.bsp> = convert BSP to AAS\n" " reach <filter.bsp> = compute reachability & clusters\n" " cluster <filter.bsp> = compute clusters\n" " aasopt <filter.aas> = optimize aas file\n" " aasinfo <filter.aas> = show AAS file info\n" " output <output path> = set output path\n" " threads <X> = set number of threads to X\n" " cfg <filename> = use this cfg file\n" " optimize = enable optimization\n" " noverbose = disable verbose output\n" " breadthfirst = breadth first bsp building\n" " nobrushmerge = don't merge brushes\n" " noliquids = don't write liquids to map\n" " freetree = free the bsp tree\n" " nocsg = disables brush chopping\n" #ifdef ZTMAUTOARGS " noforcesidesvisible = don't force all sides to be visible\n" " nograpplereach = don't calculate grapple reachabilities\n" #else " forcesidesvisible = force all sides to be visible\n" " grapplereach = calculate grapple reachabilities\n" #endif /* " noweld = disables weld\n" " noshare = disables sharing\n" " notjunc = disables juncs\n" " nowater = disables water brushes\n" " noprune = disables node prunes\n" " nomerge = disables face merging\n" " nosubdiv = disables subdeviding\n" " nodetail = disables detail brushes\n" " fulldetail = enables full detail\n" " onlyents = only compile entities with bsp\n" " micro <volume>\n" " = sets the micro volume to the given float\n" " leaktest = perform a leak test\n" " verboseentities\n" " = enable entity verbose mode\n" " chop <subdivide_size>\n" " = sets the subdivide size to the given float\n"*/ "\n"); } //end else Log_Print("BSPC run time is %5.0f seconds\n", I_FloatTime() - start_time); Log_Close(); //close the log file return 0; } //end of the function main
int main( int argc, char **argv ) { int i, comp = 0; char outputpath[MAX_PATH] = ""; char filename[MAX_PATH] = "unknown"; quakefile_t *qfiles, *qf; // Ridah, allow to specify an extension for multiple AAS files per map int has_ext = 0; // done. // Ridah, set the world pointer up for reachabilities aasworld = aasworlds; AAS_SetWorldPointer( &( *aasworld ) ); // done. myargc = argc; myargv = argv; Log_Open( "bspc.log" ); //open a log file Log_Print( "BSPC version " BSPC_VERSION ", %s %s by Mr Elusive\n", __DATE__, __TIME__ ); DefaultCfg(); for ( i = 1; i < argc; i++ ) { if ( !stricmp( argv[i],"-threads" ) ) { if ( i + 1 >= argc ) { i = 0; break; } numthreads = atoi( argv[++i] ); Log_Print( "threads = %d\n", numthreads ); } //end if else if ( !stricmp( argv[i], "-noverbose" ) ) { Log_Print( "verbose = false\n" ); verbose = false; } //end else if else if ( !stricmp( argv[i], "-nocsg" ) ) { Log_Print( "nocsg = true\n" ); nocsg = true; } //end else if else if ( !stricmp( argv[i], "-optimize" ) ) { Log_Print( "optimize = true\n" ); optimize = true; } //end else if /* else if (!stricmp(argv[i],"-glview")) { glview = true; } //end else if else if (!stricmp(argv[i], "-draw")) { Log_Print("drawflag = true\n"); drawflag = true; } //end else if else if (!stricmp(argv[i], "-noweld")) { Log_Print("noweld = true\n"); noweld = true; } //end else if else if (!stricmp(argv[i], "-noshare")) { Log_Print("noshare = true\n"); noshare = true; } //end else if else if (!stricmp(argv[i], "-notjunc")) { Log_Print("notjunc = true\n"); notjunc = true; } //end else if else if (!stricmp(argv[i], "-nowater")) { Log_Print("nowater = true\n"); nowater = true; } //end else if else if (!stricmp(argv[i], "-noprune")) { Log_Print("noprune = true\n"); noprune = true; } //end else if else if (!stricmp(argv[i], "-nomerge")) { Log_Print("nomerge = true\n"); nomerge = true; } //end else if else if (!stricmp(argv[i], "-nosubdiv")) { Log_Print("nosubdiv = true\n"); nosubdiv = true; } //end else if else if (!stricmp(argv[i], "-nodetail")) { Log_Print("nodetail = true\n"); nodetail = true; } //end else if else if (!stricmp(argv[i], "-fulldetail")) { Log_Print("fulldetail = true\n"); fulldetail = true; } //end else if else if (!stricmp(argv[i], "-onlyents")) { Log_Print("onlyents = true\n"); onlyents = true; } //end else if else if (!stricmp(argv[i], "-micro")) { if (i + 1 >= argc) {i = 0; break;} microvolume = atof(argv[++i]); Log_Print("microvolume = %f\n", microvolume); } //end else if else if (!stricmp(argv[i], "-leaktest")) { Log_Print("leaktest = true\n"); leaktest = true; } //end else if else if (!stricmp(argv[i], "-verboseentities")) { Log_Print("verboseentities = true\n"); verboseentities = true; } //end else if else if (!stricmp(argv[i], "-chop")) { if (i + 1 >= argc) {i = 0; break;} subdivide_size = atof(argv[++i]); Log_Print("subdivide_size = %f\n", subdivide_size); } //end else if else if (!stricmp (argv[i], "-tmpout")) { strcpy (outbase, "/tmp"); Log_Print("temp output\n"); } //end else if */ #ifdef ME else if ( !stricmp( argv[i], "-freetree" ) ) { freetree = true; Log_Print( "freetree = true\n" ); } //end else if else if ( !stricmp( argv[i], "-grapplereach" ) ) { calcgrapplereach = true; Log_Print( "grapplereach = true\n" ); } //end else if else if ( !stricmp( argv[i], "-nobrushmerge" ) ) { nobrushmerge = true; Log_Print( "nobrushmerge = true\n" ); } //end else if else if ( !stricmp( argv[i], "-noliquids" ) ) { noliquids = true; Log_Print( "noliquids = true\n" ); } //end else if else if ( !stricmp( argv[i], "-forcesidesvisible" ) ) { forcesidesvisible = true; Log_Print( "forcesidesvisible = true\n" ); } //end else if else if ( !stricmp( argv[i], "-output" ) ) { if ( i + 1 >= argc ) { i = 0; break; } if ( access( argv[i + 1], 0x04 ) ) { Warning( "the folder %s does not exist", argv[i + 1] ); } strcpy( outputpath, argv[++i] ); } //end else if else if ( !stricmp( argv[i], "-breadthfirst" ) ) { use_nodequeue = true; Log_Print( "breadthfirst = true\n" ); } //end else if else if ( !stricmp( argv[i], "-cfg" ) ) { if ( i + 1 >= argc ) { i = 0; break; } if ( !LoadCfgFile( argv[++i] ) ) { exit( 0 ); } } //end else if else if ( !stricmp( argv[i], "-bsp2map" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_BSP2MAP; qfiles = GetArgumentFiles( argc, argv, &i, "bsp" ); } //end else if else if ( !stricmp( argv[i], "-bsp2aas" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_BSP2AAS; qfiles = GetArgumentFiles( argc, argv, &i, "bsp" ); } //end else if else if ( !stricmp( argv[i], "-aasall" ) ) { if ( i + 1 >= argc ) { i = 0; break; } CreateAASFilesForAllBSPFiles( argv[++i] ); } //end else if else if ( !stricmp( argv[i], "-reach" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_REACH; qfiles = GetArgumentFiles( argc, argv, &i, "bsp" ); } //end else if else if ( !stricmp( argv[i], "-cluster" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_CLUSTER; qfiles = GetArgumentFiles( argc, argv, &i, "bsp" ); } //end else if else if ( !stricmp( argv[i], "-aasinfo" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_AASINFO; qfiles = GetArgumentFiles( argc, argv, &i, "aas" ); } //end else if else if ( !stricmp( argv[i], "-aasopt" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_AASOPTIMIZE; qfiles = GetArgumentFiles( argc, argv, &i, "aas" ); } //end else if else if ( !stricmp( argv[i], "-tetra" ) ) { if ( i + 1 >= argc ) { i = 0; break; } comp = COMP_TETRA; qfiles = GetArgumentFiles( argc, argv, &i, "aas" ); } //end else if // Ridah, allow to specify an extension for multiple AAS files per map else if ( !stricmp( argv[i], "-ext" ) ) { if ( i + 1 >= argc ) { i = 0; break; } strcpy( aas_extension, argv[++i] ); has_ext = 1; } //end else if // done. #endif //ME else { Log_Print( "unknown parameter %s\n", argv[i] ); break; } //end else } //end for //if there are parameters and there's no mismatch in one of the parameters if ( argc > 1 && i == argc ) { switch ( comp ) { case COMP_BSP2MAP: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { //copy the output path strcpy( filename, outputpath ); //append the bsp file base AppendPathSeperator( filename, MAX_PATH ); ExtractFileBase( qf->origname, &filename[strlen( filename )] ); //append .map strcat( filename, ".map" ); // Log_Print( "bsp2map: %s to %s\n", qf->origname, filename ); if ( qf->type != QFILETYPE_BSP ) { Warning( "%s is probably not a BSP file\n", qf->origname ); } // LoadMapFromBSP( qf ); //write the map file WriteMapFile( filename ); } //end for break; } //end case case COMP_BSP2AAS: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { AASOuputFile( qf, outputpath, filename ); // Log_Print( "bsp2aas: %s to %s\n", qf->origname, filename ); if ( qf->type != QFILETYPE_BSP ) { Warning( "%s is probably not a BSP file\n", qf->origname ); } //set before map loading create_aas = 1; LoadMapFromBSP( qf ); //create the AAS file AAS_Create( filename ); //if it's a Quake3 map calculate the reachabilities and clusters if ( loadedmaptype == MAPTYPE_QUAKE3 ) { AAS_CalcReachAndClusters( qf ); } // if ( optimize ) { AAS_Optimize(); } // //write out the stored AAS file if ( !AAS_WriteAASFile( filename ) ) { Error( "error writing %s\n", filename ); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_REACH: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { AASOuputFile( qf, outputpath, filename ); // Log_Print( "reach: %s to %s\n", qf->origname, filename ); if ( qf->type != QFILETYPE_BSP ) { Warning( "%s is probably not a BSP file\n", qf->origname ); } //if the AAS file exists in the output directory if ( !access( filename, 0x04 ) ) { if ( !AAS_LoadAASFile( filename, 0, 0 ) ) { Error( "error loading aas file %s\n", filename ); } //end if //assume it's a Quake3 BSP file loadedmaptype = MAPTYPE_QUAKE3; } //end if else { Warning( "AAS file %s not found in output folder\n", filename ); Log_Print( "creating %s...\n", filename ); //set before map loading create_aas = 1; LoadMapFromBSP( qf ); //create the AAS file AAS_Create( filename ); } //end else //if it's a Quake3 map calculate the reachabilities and clusters if ( loadedmaptype == MAPTYPE_QUAKE3 ) { AAS_CalcReachAndClusters( qf ); } //end if // if ( optimize ) { AAS_Optimize(); } //write out the stored AAS file if ( !AAS_WriteAASFile( filename ) ) { Error( "error writing %s\n", filename ); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_CLUSTER: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { AASOuputFile( qf, outputpath, filename ); // Log_Print( "cluster: %s to %s\n", qf->origname, filename ); if ( qf->type != QFILETYPE_BSP ) { Warning( "%s is probably not a BSP file\n", qf->origname ); } //if the AAS file exists in the output directory if ( !access( filename, 0x04 ) ) { if ( !AAS_LoadAASFile( filename, 0, 0 ) ) { Error( "error loading aas file %s\n", filename ); } //end if //assume it's a Quake3 BSP file loadedmaptype = MAPTYPE_QUAKE3; //if it's a Quake3 map calculate the clusters if ( loadedmaptype == MAPTYPE_QUAKE3 ) { ( *aasworld ).numclusters = 0; AAS_InitBotImport(); AAS_InitClustering(); } //end if } //end if else { Warning( "AAS file %s not found in output folder\n", filename ); Log_Print( "creating %s...\n", filename ); //set before map loading create_aas = 1; LoadMapFromBSP( qf ); //create the AAS file AAS_Create( filename ); //if it's a Quake3 map calculate the reachabilities and clusters if ( loadedmaptype == MAPTYPE_QUAKE3 ) { AAS_CalcReachAndClusters( qf ); } } //end else // if ( optimize ) { AAS_Optimize(); } //write out the stored AAS file if ( !AAS_WriteAASFile( filename ) ) { Error( "error writing %s\n", filename ); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_AASOPTIMIZE: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { AASOuputFile( qf, outputpath, filename ); // Log_Print( "optimizing: %s to %s\n", qf->origname, filename ); if ( qf->type != QFILETYPE_AAS ) { Warning( "%s is probably not a AAS file\n", qf->origname ); } // AAS_InitBotImport(); // if ( !AAS_LoadAASFile( qf->filename, qf->offset, qf->length ) ) { Error( "error loading aas file %s\n", qf->filename ); } //end if AAS_Optimize(); //write out the stored AAS file if ( !AAS_WriteAASFile( filename ) ) { Error( "error writing %s\n", filename ); } //end if //deallocate memory AAS_FreeMaxAAS(); } //end for break; } //end case case COMP_AASINFO: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { AASOuputFile( qf, outputpath, filename ); // Log_Print( "aas info for: %s\n", filename ); if ( qf->type != QFILETYPE_AAS ) { Warning( "%s is probably not a AAS file\n", qf->origname ); } // AAS_InitBotImport(); // if ( !AAS_LoadAASFile( qf->filename, qf->offset, qf->length ) ) { Error( "error loading aas file %s\n", qf->filename ); } //end if AAS_ShowTotals(); } //end for } //end case case COMP_TETRA: { if ( !qfiles ) { Log_Print( "no files found\n" ); } for ( qf = qfiles; qf; qf = qf->next ) { //TH_AASToTetrahedrons(qf->filename); } //end for break; } //end case default: { Log_Print( "don't know what to do\n" ); break; } //end default } //end switch } //end if else { Log_Print( "Usage: bspc [-<switch> [-<switch> ...]]\n" #if defined( WIN32 ) || defined( _WIN32 ) "Example 1: bspc -bsp2aas d:\\quake3\\baseq3\\maps\\mymap?.bsp\n" "Example 2: bspc -bsp2aas d:\\quake3\\baseq3\\pak0.pk3\\maps/q3dm*.bsp\n" #else "Example 1: bspc -bsp2aas /quake3/baseq3/maps/mymap?.bsp\n" "Example 2: bspc -bsp2aas /quake3/baseq3/pak0.pk3/maps/q3dm*.bsp\n" #endif "\n" "Switches:\n" //" bsp2map <[pakfilter/]filter.bsp> = convert BSP to MAP\n" " bsp2aas <[pakfilter/]filter.bsp> = convert BSP to AAS\n" //" aasall <quake3folder> = create AAS files for all BSPs\n" " reach <filter.bsp> = compute reachability & clusters\n" " cluster <filter.aas> = compute clusters\n" " aasopt <filter.aas> = optimize aas file\n" //" tetra <filter.aas> = tetrahedral decomposition\n" " output <output path> = set output path\n" " threads <X> = set number of threads to X\n" " cfg <filename> = use this cfg file\n" " optimize = enable optimization\n" " noverbose = disable verbose output\n" " breadthfirst = breadth first bsp building\n" " nobrushmerge = don't merge brushes\n" " noliquids = don't write liquids to map\n" " freetree = free the bsp tree\n" " nocsg = disables brush chopping\n" " forcesidesvisible = force all sides to be visible\n" " grapplereach = calculate grapple reachabilities\n" /* " glview = output a GL view\n" " draw = enables drawing\n" " noweld = disables weld\n" " noshare = disables sharing\n" " notjunc = disables juncs\n" " nowater = disables water brushes\n" " noprune = disables node prunes\n" " nomerge = disables face merging\n" " nosubdiv = disables subdeviding\n" " nodetail = disables detail brushes\n" " fulldetail = enables full detail\n" " onlyents = only compile entities with bsp\n" " micro <volume>\n" " = sets the micro volume to the given float\n" " leaktest = perform a leak test\n" " verboseentities\n" " = enable entity verbose mode\n" " chop <subdivide_size>\n" " = sets the subdivide size to the given float\n"*/ "\n" ); } //end else Log_Close(); //close the log file return 0; } //end of the function main
//=========================================================================== // aas data is useless after writing to file because it is byte swapped // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== qboolean AAS_WriteAASFile( char *filename ) { aas_header_t header; FILE *fp; Log_Print( "writing %s\n", filename ); AAS_ShowTotals(); //swap the aas data AAS_SwapAASData(); //initialize the file header memset( &header, 0, sizeof( aas_header_t ) ); header.ident = LittleLong( AASID ); header.version = LittleLong( AASVERSION ); header.bspchecksum = LittleLong( ( *aasworld ).bspchecksum ); //open a new file fp = fopen( filename, "wb" ); if ( !fp ) { Log_Print( "error opening %s\n", filename ); return false; } //end if //write the header if ( fwrite( &header, sizeof( aas_header_t ), 1, fp ) < 1 ) { fclose( fp ); return false; } //end if //add the data lumps to the file if ( !AAS_WriteAASLump( fp, &header, AASLUMP_BBOXES, ( *aasworld ).bboxes, ( *aasworld ).numbboxes * sizeof( aas_bbox_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_VERTEXES, ( *aasworld ).vertexes, ( *aasworld ).numvertexes * sizeof( aas_vertex_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PLANES, ( *aasworld ).planes, ( *aasworld ).numplanes * sizeof( aas_plane_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_EDGES, ( *aasworld ).edges, ( *aasworld ).numedges * sizeof( aas_edge_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_EDGEINDEX, ( *aasworld ).edgeindex, ( *aasworld ).edgeindexsize * sizeof( aas_edgeindex_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_FACES, ( *aasworld ).faces, ( *aasworld ).numfaces * sizeof( aas_face_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_FACEINDEX, ( *aasworld ).faceindex, ( *aasworld ).faceindexsize * sizeof( aas_faceindex_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_AREAS, ( *aasworld ).areas, ( *aasworld ).numareas * sizeof( aas_area_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_AREASETTINGS, ( *aasworld ).areasettings, ( *aasworld ).numareasettings * sizeof( aas_areasettings_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_REACHABILITY, ( *aasworld ).reachability, ( *aasworld ).reachabilitysize * sizeof( aas_reachability_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_NODES, ( *aasworld ).nodes, ( *aasworld ).numnodes * sizeof( aas_node_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PORTALS, ( *aasworld ).portals, ( *aasworld ).numportals * sizeof( aas_portal_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_PORTALINDEX, ( *aasworld ).portalindex, ( *aasworld ).portalindexsize * sizeof( aas_portalindex_t ) ) ) { return false; } if ( !AAS_WriteAASLump( fp, &header, AASLUMP_CLUSTERS, ( *aasworld ).clusters, ( *aasworld ).numclusters * sizeof( aas_cluster_t ) ) ) { return false; } //rewrite the header with the added lumps fseek( fp, 0, SEEK_SET ); AAS_DData( (unsigned char *) &header + 8, sizeof( aas_header_t ) - 8 ); if ( fwrite( &header, sizeof( aas_header_t ), 1, fp ) < 1 ) { fclose( fp ); return false; } //end if //close the file fclose( fp ); return true; } //end of the function AAS_WriteAASFile