26#define VERSION "1.2.6"
30#define LIGHTING_NONE 1
31#define LIGHTING_DAY_ONLY 2
32#define LIGHTING_NIGHT_ONLY 3
37#include <sys/resource.h>
57typedef struct usagePair_s {
63 {
"Usage: ufo2map <param1 <subparam1> <subparam2> <...>> <param2> <...> [map]",
nullptr},
65 {
"Even on Windows, use / slashes in the path",
nullptr},
67 {
"\nGeneral options:",
nullptr},
68 {
" -h --help",
"print (this) help and exit"},
70 {
" -nice <prio>",
"priority level [0 = HIGH, 1 = NORMAL, 2 = IDLE]"},
72 {
" -nice <prio>",
"priority level [unix nice level from -20 to 19 where 19 is the lowest priority]"},
74 {
" -nofootstep",
"don't generate a footstep file"},
75 {
" -tracefile",
"generate two csv files describing the floors and walls found by the trace functions"},
76 {
" -debugfile (TODO)",
"generate a trace debug file. The client can load the file to highlight map obstructions"},
77 {
" -stats --statistics",
"print statistics and quit. may be used with -check or -fix"},
78 {
" -v --verbosity <int>",
"set verbosity. higher <int> gives more output"},
79 {
nullptr,
"if it is required, this should be the first option"},
80 {
nullptr,
"0 - no stdout, 1 - only check/fix messages, 2 - (compile) only mapname"},
81 {
nullptr,
"2 - (check/fix) mapname if findings, 4 - normal output,"},
82 {
nullptr,
"5 - extra output, 6 - dump (a lot extra from BSPing)"},
84 {
" -V --version",
"return Version and Revision level"},
85 {
" -material",
"generate a material (.mat) file, do not proceed to compilation"},
86 {
"\nLighting options:",
nullptr},
87 {
" -extra",
"extra light samples"},
88 {
" -nolighting TYPE",
"don't perform the lighting calculations, where TYPE is one of day, night, all"},
89 {
nullptr,
"default is all"},
90 {
" -quant",
"lightquant - lightmap resolution downscale (e.g. 4 = 1 << 4) (values between 1 and 6)"},
91 {
" -scale",
"global light scale factor"},
92 {
" -saturation",
"saturation factor (e.g. 1.5 - default is 1.0)"},
93 {
" -contrast",
"contrast factor (e.g. 1.05, default is 1.0)"},
94 {
" -t --threads",
"thread amount"},
95 {
"\nBinary space partitioning (BSPing) options:",
nullptr},
96 {
" -block <xl> <yl>",
""},
97 {
" -blocks <xl> <yl> <xh> <yh>",
""},
98 {
" -subdivide",
"subdivide brushes for better light effects (but higher polycount)"},
99 {
" -surface",
"surface light scaling (float value)"},
100 {
" -entity",
"entity light scaling (float value)"},
101 {
" -fulldetail",
"don't treat details (and trans surfaces) as details"},
102 {
" -info",
"print bsp file info"},
103 {
" -micro <float>",
"warn if a brush has a volume lower than the specified float."},
104 {
nullptr,
"brushes are tested after CSG."},
105 {
" -nobackclip",
"draw downward pointing faces. (so actors cannot see up through floors"},
106 {
nullptr,
"in first person view). default is to set SURF_NODRAW to downard faces."},
108 {
" -gamedir",
"Add another game dir to the search directories"},
109 {
" -nodetail",
"skip detail brushes"},
110 {
" -nomerge",
"skip node face merging"},
111 {
" -noprune",
"don't prune (or cut) nodes"},
114 {
" -nowater",
"skip water brushes in compilation"},
116 {
" -onlyents",
"modify existing bsp file with entities from map file"},
117 {
" -exportlightmaps",
"write lightmaps into tga images"},
118 {
" -verboseentities",
"also be verbose about submodels (entities)"},
119 {
"\nMapping options:",
nullptr},
120 {
"\n These options operate on map file only. No bsp file is created.",
nullptr},
121 {
" Output prefixed by an asterisk (*) indicates operations that would change the map file.",
nullptr},
122 {
" -check",
"check source map, only print information."},
123 {
" -fix",
"same subparameters as -check, changes the source map file."},
124 {
" \n subparameters for -check and -fix",
nullptr},
125 {
" all",
"performs all checks and fixes. This is the default."},
126 {
" bru brushes",
"includes 'lvl tex mfc mbr'. Performs all checks and fixes associated with brushes."},
127 {
" ent entities",
"performs all checks and fixes associated with entities."},
128 {
" con contained",
"checks for brushes contained entirely within other brushes. includes coincident duplicates."},
129 {
" isc intersection",
"report intersection between optimisable brushes from worldspawn and func_group entities"},
130 {
nullptr,
"this is not included in all or bru as it is not always a bad thing"},
131 {
" mbr microbrush <float> ",
"test for brushes smaller than <float> unit^3. this is done without the csg"},
132 {
nullptr,
"step, unlike the bsp -micro option. default 1 unit^3."},
133 {
" lvl levelflags",
"if no levelflags for a brush or entity are set, all of them are set"},
134 {
" flv filllevelflags",
"ensure set levelflag bits are uninterrupted"},
135 {
" ndr nodraws",
"assigns SURF_NODRAW to hidden faces"},
136 {
" tex textures",
"warns when no texture or error texture is assigned."},
137 {
nullptr,
"ensures special textures and content/surface flags are consistent."},
138 {
" mfc mixedfacecontents",
"ensures the contentflags are the same on each face of each brush."},
139 {
" zft zfighting",
"intersecting brushes with a common face: prevent textures shimmering together"},
155 if (
v->flags &&
v->desc) {
156 const int len = strlen(
v->flags);
157 maxFlagsLen =
len > maxFlagsLen ?
len : maxFlagsLen;
161 if (
v->flags &&
v->desc)
162 Com_Printf(
"%-*s: %s\n", maxFlagsLen,
v->flags,
v->desc);
172 char out_buffer[4096];
179 printf(
"%s", out_buffer);
191 return (msgVerbLevel >
config.verbosity);
203 char out_buffer[4096];
210 printf(
"%s", out_buffer);
220 for (
i = 1;
i < argc;
i++) {
225 if (strlen(argv[
i + 1]) == 1)
228 }
else if (
Q_streq(argv[
i],
"-noweld")) {
232 }
else if (
Q_streq(argv[
i],
"--statistics") ||
Q_streq(argv[
i],
"-stats")) {
235 config.performMapCheck =
true;
240 const int iInitial =
i;
244 config.performMapCheck =
true;
250 while (++
i < (argc - 1) && argv[
i][0] !=
'-') {
253 config.chkEntities =
true;
259 config.chkContained =
true;
262 config.chkFillLevelFlags =
true;
265 config.chkLevelFlags =
true;
268 config.chkTextures =
true;
274 config.chkIntersection =
true;
275 }
else if (
Q_streq(argv[
i],
"mixedfacecontents") ||
Q_streq(argv[
i],
"mfc")) {
277 config.chkMixedFaceContents =
true;
280 if (atof(argv[
i + 1]) > 0.0001) {
281 config.mapMicrovol = atof(argv[
i + 1]);
288 }
else if (
Q_streq(argv[
i],
"all")) {
292 Verb_Printf(
VERB_LESS,
" WARNING: %s subparameter not understood:%s try --help for more info\n",
config.fixMap ?
"fix" :
"check", argv[
i]);
307 }
else if (
Q_streq(argv[
i],
"-info")) {
309 }
else if (
Q_streq(argv[
i],
"-nocsg")) {
312 }
else if (
Q_streq(argv[
i],
"-gamedir")) {
318 }
else if (
Q_streq(argv[
i],
"-noshare")) {
321 }
else if (
Q_streq(argv[
i],
"-notjunc")) {
324 }
else if (
Q_streq(argv[
i],
"-nowater")) {
327 }
else if (
Q_streq(argv[
i],
"-nice")) {
329 HANDLE proc = GetCurrentProcess();
334 SetPriorityClass(proc, HIGH_PRIORITY_CLASS);
338 SetPriorityClass(proc, NORMAL_PRIORITY_CLASS);
342 SetPriorityClass(proc, IDLE_PRIORITY_CLASS);
350 if (setpriority(PRIO_PROCESS, 0,
config.nice))
353 }
else if (
Q_streq(argv[
i],
"-noprune")) {
356 }
else if (
Q_streq(argv[
i],
"-nofootstep")) {
357 config.generateFootstepFile =
false;
359 }
else if (
Q_streq(argv[
i],
"-tracefile")) {
360 config.generateTraceFile =
true;
362 }
else if (
Q_streq(argv[
i],
"-debugtrace")) {
363 config.generateDebugTrace =
true;
365 }
else if (
Q_streq(argv[
i],
"-material")) {
366 config.generateMaterialFile =
true;
368 }
else if (
Q_streq(argv[
i],
"-nomerge")) {
371 }
else if (
Q_streq(argv[
i],
"-nosubdiv")) {
374 }
else if (
Q_streq(argv[
i],
"-nodetail")) {
377 }
else if (
Q_streq(argv[
i],
"-fulldetail")) {
380 }
else if (
Q_streq(argv[
i],
"-onlyents")) {
383 }
else if (
Q_streq(argv[
i],
"-exportlightmaps")) {
385 config.exportLightmaps =
true;
386 }
else if (
Q_streq(argv[
i],
"-micro")) {
387 config.microvolume = atof(argv[
i + 1]);
390 }
else if (
Q_streq(argv[
i],
"-verboseentities")) {
392 config.verboseentities =
true;
393 }
else if (
Q_streq(argv[
i],
"-subdivide")) {
394 config.subdivideSize = atof(argv[
i + 1]);
397 }
else if (
Q_streq(argv[
i],
"-block")) {
402 }
else if (
Q_streq(argv[
i],
"-blocks")) {
403 config.block_xl = atoi(argv[
i + 1]);
404 config.block_yl = atoi(argv[
i + 2]);
405 config.block_xh = atoi(argv[
i + 3]);
406 config.block_yh = atoi(argv[
i + 4]);
410 }
else if (
Q_streq(argv[
i],
"-nobackclip")) {
413 }
else if (
Q_streq(argv[
i],
"-extra")) {
414 config.extrasamples =
true;
416 }
else if (
Q_streq(argv[
i],
"-soft")) {
417 config.extrasamples =
true;
421 }
else if (
Q_streq(argv[
i],
"-quant")) {
428 }
else if (
Q_streq(argv[
i],
"-scale")) {
429 config.brightness = atof(argv[
i + 1]);
431 }
else if (
Q_streq(argv[
i],
"-saturation")) {
432 config.saturation = atof(argv[
i + 1]);
435 }
else if (
Q_streq(argv[
i],
"-contrast")) {
436 config.contrast = atof(argv[
i + 1]);
439 }
else if (
Q_streq(argv[
i],
"-surface")) {
440 config.surface_scale *= atof(argv[
i + 1]);
443 }
else if (
Q_streq(argv[
i],
"-entity")) {
444 config.entity_scale *= atof(argv[
i + 1]);
447 }
else if (
Q_streq(argv[
i],
"-nolighting")) {
453 }
else if (
Q_streq(argv[
i + 1],
"night")) {
467 }
else if (
i < (argc - 1)) {
474 Sys_Error(
"do not specify both -fix and -check");
479 config.generateFootstepFile =
false;
480 config.generateMaterialFile =
false;
491 config.subdivideSize = 1024.0f;
496 config.microvolume = 1.0f;
497 config.mapMicrovol = 1.0f;
519 config.surface_scale = 0.4f;
520 config.entity_scale = 1.0f;
522 config.generateFootstepFile =
true;
524 config.generateTraceFile =
false;
525 config.generateDebugTrace =
false;
534 const char*
mode =
nullptr;
536 if (
config.performMapCheck) {
538 }
else if (
config.fixMap) {
547int main (
int argc,
char** argv)
551 double begin, start, end;
566 Sys_Error(
"At least provide 1 argument: the map filename.");
575 start = time(
nullptr);
578 Q_strncpyz(normMapFile, argv[argc-1],
sizeof(normMapFile));
583 if (
config.gamedir[0] !=
'\0') {
588 if (
config.gamedir[0] !=
'\0'){
608 strncpy(bspFilename,
mapFilename,
sizeof(bspFilename) - 1);
637 }
else if (
config.exportLightmaps) {
672 if (
config.chkIntersection)
691 }
else if (
config.generateMaterialFile) {
719 start = time(
nullptr);
727 config.compile_for_day = 1;
728 start = time(
nullptr);
736 }
else if (!
config.exportLightmaps) {
void WriteMapFile(const char *filename)
void LoadMapFile(const char *filename)
void SetModelNumbers(void)
Set the model numbers for SOLID_BSP or SOLID_TRIGGER entities like func_door or func_breakable.
const char * UnparseEntities(void)
Generates the curTile->entdata string from all the entities.
void PrintBSPFileSizes(void)
Dumps info about current file.
long WriteBSPFile(const char *filename)
Swaps the bsp file in place, so it should not be referenced again.
dMapTile_t * LoadBSPFile(const char *filename)
void Check_ContainedBrushes(void)
find duplicated brushes and brushes contained inside brushes
void CheckFlagsBasedOnTextures(void)
sets content flags based on textures
void CheckTexturesBasedOnFlags(void)
check that sides have textures and that where content/surface flags are set the texture is correct.
void CheckMixedFaceContents(void)
contentflags should be the same on each face of a brush. print warnings if they are not....
void CheckNodraws(void)
check for faces which can safely be set to SURF_NODRAW because they are pressed against the faces of ...
void Check_BrushIntersection(void)
reports intersection between optimisable map brushes
void CheckLevelFlags(void)
sets all levelflags, if none are set.
void CheckFillLevelFlags(void)
ensures set levelflags are in one contiguous block
void CheckMapMicro(void)
report brushes from the map below 1 unit^3
void CheckZFighting(void)
check all brushes for overlapping shared faces
Performs check on a loaded mapfile, and makes changes that can be saved back to the source map.
void Check_Stats(void)
print map stats on -stats
void CheckEntities(void)
Perform an entity check.
void Check_Free(void)
free the mapbrush_t::nearBrushes, compositeSides and entitiesdef.h stuff.
Performs check on a loaded mapfile, and makes changes that can be saved back to the source map.
memPool_t * com_genericPool
memPool_t * com_fileSysPool
void FS_InitFilesystem(bool writeToHomeDir)
void FS_NormPath(char *path)
Convert operating systems path separators to ufo virtual filesystem separators (/).
void FS_AddGameDirectory(const char *dir, bool write)
Adds the directory to the head of the search path.
void Sys_Error(const char *error,...)
void LightWorld(void)
Build the lightmap out of light entities and surface lights (patches).
void BuildVertexNormals(void)
Calculate per-vertex (instead of per-plane) normal vectors. This is done by finding all of the faces ...
void CalcTextureReflectivity(void)
Calculates the texture color that is used for light emitting surfaces.
void ExportLightmaps(const char *bspFileName)
Export the day and night lightmap and direction data for the given map.
vec_t ColorNormalize(const vec3_t in, vec3_t out)
void AngleVectors(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Create the rotation matrix in order to rotate something.
#define Mem_CreatePool(name)
void format(__printf__, 1, 2)))
QGL_EXTERN GLuint GLchar GLuint * len
QGL_EXTERN int GLboolean GLfloat * v
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
void Com_DefaultExtension(char *path, size_t len, const char *extension)
Sets a default extension if there is none.
int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Safe (null terminating) vsnprintf implementation.
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
bool Q_strreplace(const char *source, const char *pattern, const char *replace, char *dest, size_t destsize)
Replaces the first occurence of the given pattern in the source string with the given replace string.
static char mapFilename[MAX_OSPATH]
bool AbortPrint(const verbosityLevel_t msgVerbLevel)
return nonzero if printing should be aborted based on the command line verbosity level and the import...
static void U2M_SetDefaultConfigValues(void)
Set default values.
#define LIGHTING_DAY_ONLY
int main(int argc, char **argv)
static const usagePair_t usageArray[]
#define LIGHTING_NIGHT_ONLY
void Verb_Printf(const verbosityLevel_t msgVerbLevel, const char *format,...)
decides wether to proceed with output based on verbosity level
void PrintMapName(void)
print name in concise form for lower verbosity levels. verbosity check done before calling this funct...
void Com_Printf(const char *format,...)
static void Usage(void)
print usage information.
static void U2M_Parameter(int argc, char **argv)
Check for bsping, lighting and checking/fixing command line parameters.
#define Vector2Set(v, x, y)
#define VectorSet(v, x, y, z)