📄 bspc.c
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#if defined(WIN32) || defined(_WIN32)
#include <direct.h>
#include <windows.h>
#include <sys/types.h>
#include <sys/stat.h>
#else
#include <unistd.h>
#include <glob.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#include "qbsp.h"
#include "l_mem.h"
#include "../botlib/aasfile.h"
#include "../botlib/be_aas_cluster.h"
#include "../botlib/be_aas_optimize.h"
#include "aas_create.h"
#include "aas_store.h"
#include "aas_file.h"
#include "aas_cfg.h"
#include "be_aas_bspc.h"
extern int use_nodequeue; //brushbsp.c
extern int calcgrapplereach; //be_aas_reach.c
float subdivide_size = 240;
char source[1024];
char name[1024];
vec_t microvolume = 1.0;
char outbase[32];
int entity_num;
aas_settings_t aassettings;
qboolean noprune; //don't prune nodes (bspc.c)
qboolean glview; //create a gl view
qboolean nodetail; //don't use detail brushes (map.c)
qboolean fulldetail; //use but don't mark detail brushes (map.c)
qboolean onlyents; //only process the entities (bspc.c)
qboolean nomerge; //don't merge bsp node faces (faces.c)
qboolean nowater; //don't use the water brushes (map.c)
qboolean nocsg; //don't carve intersecting brushes (bspc.c)
qboolean noweld; //use unique face vertexes (faces.c)
qboolean noshare; //don't share bsp edges (faces.c)
qboolean nosubdiv; //don't subdivide bsp node faces (faces.c)
qboolean notjunc; //don't create tjunctions (edge melting) (faces.c)
qboolean optimize; //enable optimisation
qboolean leaktest; //perform a leak test
qboolean verboseentities;
qboolean freetree; //free the bsp tree when not needed anymore
qboolean create_aas; //create an .AAS file
qboolean nobrushmerge; //don't merge brushes
qboolean lessbrushes; //create less brushes instead of correct texture placement
qboolean cancelconversion; //true if the conversion is being cancelled
qboolean noliquids; //no liquids when writing map file
qboolean forcesidesvisible; //force all brush sides to be visible when loaded from bsp
qboolean capsule_collision = 0;
/*
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ProcessWorldModel (void)
{
entity_t *e;
tree_t *tree;
qboolean leaked;
int brush_start, brush_end;
e = &entities[entity_num];
brush_start = e->firstbrush;
brush_end = brush_start + e->numbrushes;
leaked = false;
//process the whole world in one time
tree = ProcessWorldBrushes(brush_start, brush_end);
//create the bsp tree portals
MakeTreePortals(tree);
//mark all leafs that can be reached by entities
if (FloodEntities(tree))
{
FillOutside(tree->headnode);
} //end if
else
{
Log_Print("**** leaked ****\n");
leaked = true;
LeakFile(tree);
if (leaktest)
{
Log_Print("--- MAP LEAKED ---\n");
exit(0);
} //end if
} //end else
MarkVisibleSides (tree, brush_start, brush_end);
FloodAreas (tree);
#ifndef ME
if (glview) WriteGLView(tree, source);
#endif
MakeFaces(tree->headnode);
FixTjuncs(tree->headnode);
//NOTE: Never prune the nodes because the portals
// are screwed when prunning is done and as
// a result portal writing will crash
//if (!noprune) PruneNodes(tree->headnode);
WriteBSP(tree->headnode);
if (!leaked) WritePortalFile(tree);
Tree_Free(tree);
} //end of the function ProcessWorldModel
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ProcessSubModel (void)
{
entity_t *e;
int start, end;
tree_t *tree;
bspbrush_t *list;
vec3_t mins, maxs;
e = &entities[entity_num];
start = e->firstbrush;
end = start + e->numbrushes;
mins[0] = mins[1] = mins[2] = -4096;
maxs[0] = maxs[1] = maxs[2] = 4096;
list = MakeBspBrushList(start, end, mins, maxs);
if (!nocsg) list = ChopBrushes (list);
tree = BrushBSP (list, mins, maxs);
MakeTreePortals (tree);
MarkVisibleSides (tree, start, end);
MakeFaces (tree->headnode);
FixTjuncs (tree->headnode);
WriteBSP (tree->headnode);
Tree_Free(tree);
} //end of the function ProcessSubModel
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void ProcessModels (void)
{
BeginBSPFile();
for (entity_num = 0; entity_num < num_entities; entity_num++)
{
if (!entities[entity_num].numbrushes)
continue;
Log_Print("############### model %i ###############\n", nummodels);
BeginModel();
if (entity_num == 0) ProcessWorldModel();
else ProcessSubModel();
EndModel();
if (!verboseentities)
verbose = false; // don't bother printing submodels
} //end for
EndBSPFile();
} //end of the function ProcessModels
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Win_Map2Bsp(char *bspfilename)
{
double start, end;
char path[1024];
start = I_FloatTime();
ThreadSetDefault();
//yeah sure Carmack
//numthreads = 1; // multiple threads aren't helping...
strcpy(source, ExpandArg(bspfilename));
StripExtension(source);
//delete portal and line files
sprintf(path, "%s.prt", source);
remove(path);
sprintf(path, "%s.lin", source);
remove(path);
strcpy(name, ExpandArg(bspfilename));
DefaultExtension(name, ".map"); // might be .reg
Q2_AllocMaxBSP();
//
SetModelNumbers();
SetLightStyles();
ProcessModels();
//write the BSP
Q2_WriteBSPFile(bspfilename);
Q2_FreeMaxBSP();
end = I_FloatTime();
Log_Print("%5.0f seconds elapsed\n", end-start);
} //end of the function Win_Map2Bsp
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void Map2Bsp(char *mapfilename, char *outputfilename)
{
double start, end;
char path[1024];
start = I_FloatTime ();
ThreadSetDefault ();
//yeah sure Carmack
//numthreads = 1; //multiple threads aren't helping...
//SetQdirFromPath(bspfilename);
strcpy(source, ExpandArg(mapfilename));
StripExtension(source);
// delete portal and line files
sprintf(path, "%s.prt", source);
remove(path);
sprintf(path, "%s.lin", source);
remove(path);
strcpy(name, ExpandArg(mapfilename));
DefaultExtension(name, ".map"); // might be .reg
//
// if onlyents, just grab the entites and resave
//
if (onlyents)
{
char out[1024];
Q2_AllocMaxBSP();
sprintf (out, "%s.bsp", source);
Q2_LoadBSPFile(out, 0, 0);
num_entities = 0;
Q2_LoadMapFile(name);
SetModelNumbers();
SetLightStyles();
Q2_UnparseEntities();
Q2_WriteBSPFile(out);
//
Q2_FreeMaxBSP();
} //end if
else
{
//
// start from scratch
//
Q2_AllocMaxBSP();
//load the map
Q2_LoadMapFile(name);
//create the .bsp file
SetModelNumbers();
SetLightStyles();
ProcessModels();
//write the BSP
Q2_WriteBSPFile(outputfilename);
//
Q2_FreeMaxBSP();
} //end else
end = I_FloatTime();
Log_Print("%5.0f seconds elapsed\n", end-start);
} //end of the function Map2Bsp
*/
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void AASOuputFile(quakefile_t *qf, char *outputpath, char *filename)
{
char ext[MAX_PATH];
//
if (strlen(outputpath))
{
strcpy(filename, outputpath);
//append the bsp file base
AppendPathSeperator(filename, MAX_PATH);
ExtractFileBase(qf->origname, &filename[strlen(filename)]);
//append .aas
strcat(filename, ".aas");
return;
} //end if
//
ExtractFileExtension(qf->filename, ext);
if (!stricmp(ext, "pk3") || !stricmp(ext, "pak") || !stricmp(ext, "sin"))
{
strcpy(filename, qf->filename);
while(strlen(filename) &&
filename[strlen(filename)-1] != '\\' &&
filename[strlen(filename)-1] != '/')
{
filename[strlen(filename)-1] = '\0';
} //end while
strcat(filename, "maps");
if (access(filename, 0x04)) CreatePath(filename);
//append the bsp file base
AppendPathSeperator(filename, MAX_PATH);
ExtractFileBase(qf->origname, &filename[strlen(filename)]);
//append .aas
strcat(filename, ".aas");
} //end if
else
{
strcpy(filename, qf->filename);
while(strlen(filename) &&
filename[strlen(filename)-1] != '.')
{
filename[strlen(filename)-1] = '\0';
} //end while
strcat(filename, "aas");
} //end else
} //end of the function AASOutputFile
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void CreateAASFilesForAllBSPFiles(char *quakepath)
{
#if defined(WIN32)|defined(_WIN32)
WIN32_FIND_DATA filedata;
HWND handle;
struct _stat statbuf;
#else
glob_t globbuf;
struct stat statbuf;
int j;
#endif
int done;
char filter[_MAX_PATH], bspfilter[_MAX_PATH], aasfilter[_MAX_PATH];
char aasfile[_MAX_PATH], buf[_MAX_PATH], foldername[_MAX_PATH];
quakefile_t *qf, *qf2, *files, *bspfiles, *aasfiles;
strcpy(filter, quakepath);
AppendPathSeperator(filter, sizeof(filter));
strcat(filter, "*");
#if defined(WIN32)|defined(_WIN32)
handle = FindFirstFile(filter, &filedata);
done = (handle == INVALID_HANDLE_VALUE);
while(!done)
{
_splitpath(filter, foldername, NULL, NULL, NULL);
_splitpath(filter, NULL, &foldername[strlen(foldername)], NULL, NULL);
AppendPathSeperator(foldername, _MAX_PATH);
strcat(foldername, filedata.cFileName);
_stat(foldername, &statbuf);
#else
glob(filter, 0, NULL, &globbuf);
for (j = 0; j < globbuf.gl_pathc; j++)
{
strcpy(foldername, globbuf.gl_pathv[j]);
stat(foldername, &statbuf);
#endif
//if it is a folder
if (statbuf.st_mode & S_IFDIR)
{
//
AppendPathSeperator(foldername, sizeof(foldername));
//get all the bsp files
strcpy(bspfilter, foldername);
strcat(bspfilter, "maps/*.bsp");
files = FindQuakeFiles(bspfilter);
strcpy(bspfilter, foldername);
strcat(bspfilter, "*.pk3/maps/*.bsp");
bspfiles = FindQuakeFiles(bspfilter);
for (qf = bspfiles; qf; qf = qf->next) if (!qf->next) break;
if (qf) qf->next = files;
else bspfiles = files;
//get all the aas files
strcpy(aasfilter, foldername);
strcat(aasfilter, "maps/*.aas");
files = FindQuakeFiles(aasfilter);
strcpy(aasfilter, foldername);
strcat(aasfilter, "*.pk3/maps/*.aas");
aasfiles = FindQuakeFiles(aasfilter);
for (qf = aasfiles; qf; qf = qf->next) if (!qf->next) break;
if (qf) qf->next = files;
else aasfiles = files;
//
for (qf = bspfiles; qf; qf = qf->next)
{
sprintf(aasfile, "%s/%s", qf->pakfile, qf->origname);
Log_Print("found %s\n", aasfile);
strcpy(&aasfile[strlen(aasfile)-strlen(".bsp")], ".aas");
for (qf2 = aasfiles; qf2; qf2 = qf2->next)
{
sprintf(buf, "%s/%s", qf2->pakfile, qf2->origname);
if (!stricmp(aasfile, buf))
{
Log_Print("found %s\n", buf);
break;
} //end if
} //end for
} //end for
} //end if
#if defined(WIN32)|defined(_WIN32)
//find the next file
done = !FindNextFile(handle, &filedata);
} //end while
#else
} //end for
globfree(&globbuf);
#endif
} //end of the function CreateAASFilesForAllBSPFiles
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
quakefile_t *GetArgumentFiles(int argc, char *argv[], int *i, char *ext)
{
quakefile_t *qfiles, *lastqf, *qf;
int j;
char buf[1024];
qfiles = NULL;
lastqf = NULL;
for (; (*i)+1 < argc && argv[(*i)+1][0] != '-'; (*i)++)
{
strcpy(buf, argv[(*i)+1]);
for (j = strlen(buf)-1; j >= strlen(buf)-4; j--)
if (buf[j] == '.') break;
if (j >= strlen(buf)-4)
strcpy(&buf[j+1], ext);
qf = FindQuakeFiles(buf);
if (!qf) continue;
if (lastqf) lastqf->next = qf;
else qfiles = qf;
lastqf = qf;
while(lastqf->next) lastqf = lastqf->next;
} //end for
return qfiles;
} //end of the function GetArgumentFiles
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -