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>
45 #include "../../shared/shared.h"
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"},
154 for (v = usageArray; v->
flags || v->
desc; v++)
157 maxFlagsLen = len > maxFlagsLen ? len : maxFlagsLen;
160 for (v = usageArray; v->
flags || v->
desc; v++) {
172 char out_buffer[4096];
175 va_start(argptr, format);
176 Q_vsnprintf(out_buffer,
sizeof(out_buffer), format, argptr);
179 printf(
"%s", out_buffer);
191 return (msgVerbLevel >
config.verbosity);
203 char out_buffer[4096];
206 va_start(argptr, format);
207 Q_vsnprintf(out_buffer,
sizeof(out_buffer), format, argptr);
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;
236 }
else if (
Q_streq(argv[i],
"-check") ||
Q_streq(argv[i],
"-fix")) {
240 const int iInitial =
i;
242 if (
Q_streq(argv[i],
"-check")) {
244 config.performMapCheck =
true;
246 if (
Q_streq(argv[i],
"-fix")) {
250 while (++i < (argc - 1) && argv[i][0] !=
'-') {
253 config.chkEntities =
true;
254 }
else if (
Q_streq(argv[i],
"brushes") ||
Q_streq(argv[i],
"bru")) {
257 }
else if (
Q_streq(argv[i],
"contained") ||
Q_streq(argv[i],
"con")) {
259 config.chkContained =
true;
260 }
else if (
Q_streq(argv[i],
"filllevelflags") ||
Q_streq(argv[i],
"flv")) {
262 config.chkFillLevelFlags =
true;
263 }
else if (
Q_streq(argv[i],
"levelflags") ||
Q_streq(argv[i],
"lvl")) {
265 config.chkLevelFlags =
true;
266 }
else if (
Q_streq(argv[i],
"textures") ||
Q_streq(argv[i],
"tex")) {
268 config.chkTextures =
true;
269 }
else if (
Q_streq(argv[i],
"nodraws") ||
Q_streq(argv[i],
"ndr")) {
272 }
else if (
Q_streq(argv[i],
"intersection") ||
Q_streq(argv[i],
"isc")) {
274 config.chkIntersection =
true;
275 }
else if (
Q_streq(argv[i],
"mixedfacecontents") ||
Q_streq(argv[i],
"mfc")) {
277 config.chkMixedFaceContents =
true;
278 }
else if (
Q_streq(argv[i],
"microbrush") ||
Q_streq(argv[i],
"mbr")) {
280 if (atof(argv[i + 1]) > 0.0001) {
281 config.mapMicrovol = atof(argv[i + 1]);
285 }
else if (
Q_streq(argv[i],
"zfighting") ||
Q_streq(argv[i],
"zft")) {
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]);
301 }
else if (
Q_streq(argv[i],
"-h") ||
Q_streq(argv[i],
"--help")) {
304 }
else if (
Q_streq(argv[i],
"-t") ||
Q_streq(argv[i],
"-threads")) {
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();
330 config.nice = atoi(argv[++i]);
334 SetPriorityClass(proc, HIGH_PRIORITY_CLASS);
338 SetPriorityClass(proc, NORMAL_PRIORITY_CLASS);
342 SetPriorityClass(proc, IDLE_PRIORITY_CLASS);
348 config.nice = atoi(argv[++i]);
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")) {
449 if (
Q_streq(argv[i + 1],
"day")) {
453 }
else if (
Q_streq(argv[i + 1],
"night")) {
464 }
else if (
Q_streq(argv[i],
"-V") ||
Q_streq(argv[i],
"--version")) {
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) {
547 int 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) {
743 Verb_Printf(
VERB_LESS,
"sum: %5.0f seconds elapsed - %.1g MB (%li bytes)\n\n", end - begin, (
float)size / (1024.0
f * 1024.0
f), size);
void CheckZFighting(void)
check all brushes for overlapping shared faces
void BuildVertexNormals(void)
Calculate per-vertex (instead of per-plane) normal vectors. This is done by finding all of the faces ...
Performs check on a loaded mapfile, and makes changes that can be saved back to the source map...
static void U2M_Parameter(int argc, char **argv)
Check for bsping, lighting and checking/fixing command line parameters.
Performs check on a loaded mapfile, and makes changes that can be saved back to the source map...
void PrintBSPFileSizes(void)
Dumps info about current file.
static void U2M_SetDefaultConfigValues(void)
Set default values.
void FS_AddGameDirectory(const char *dir, bool write)
Adds the directory to the head of the search path.
int Q_vsnprintf(char *str, size_t size, const char *format, va_list ap)
Safe (null terminating) vsnprintf implementation.
void Sys_Error(const char *error,...)
#define VectorSet(v, x, y, z)
memPool_t * com_genericPool
void LoadMapFile(const char *filename)
vec_t ColorNormalize(const vec3_t in, vec3_t out)
void CheckNodraws(void)
check for faces which can safely be set to SURF_NODRAW because they are pressed against the faces of ...
static char mapFilename[MAX_OSPATH]
void Com_StripExtension(const char *in, char *out, const size_t size)
Removes the file extension from a filename.
void CheckMixedFaceContents(void)
contentflags should be the same on each face of a brush. print warnings if they are not...
static const usagePair_t usageArray[]
static void Usage(void)
print usage information.
void Check_BrushIntersection(void)
reports intersection between optimisable map brushes
char baseFilename[MAX_OSPATH]
void CheckFillLevelFlags(void)
ensures set levelflags are in one contiguous block
void CheckMapMicro(void)
report brushes from the map below 1 unit^3
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
void AngleVectors(const vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Create the rotation matrix in order to rotate something.
void FS_NormPath(char *path)
Convert operating systems path separators to ufo virtual filesystem separators (/) ...
void SetModelNumbers(void)
Set the model numbers for SOLID_BSP or SOLID_TRIGGER entities like func_door or func_breakable.
void CheckTexturesBasedOnFlags(void)
check that sides have textures and that where content/surface flags are set the texture is correct...
void LightWorld(void)
Build the lightmap out of light entities and surface lights (patches)
#define Vector2Set(v, x, y)
dMapTile_t * LoadBSPFile(const char *filename)
void Com_Printf(const char *format,...)
void WriteMapFile(const char *filename)
void CalcTextureReflectivity(void)
Calculates the texture color that is used for light emitting surfaces.
void FS_InitFilesystem(bool writeToHomeDir)
#define Mem_CreatePool(name)
char const * Q_strstart(char const *str, char const *start)
Matches the start of a string.
#define LIGHTING_NIGHT_ONLY
void CheckLevelFlags(void)
sets all levelflags, if none are set.
memPool_t * com_fileSysPool
void PrintMapName(void)
print name in concise form for lower verbosity levels. verbosity check done before calling this funct...
int main(int argc, char **argv)
const char * UnparseEntities(void)
Generates the curTile->entdata string from all the entities.
void Com_DefaultExtension(char *path, size_t len, const char *extension)
Sets a default extension if there is none.
QGL_EXTERN GLuint GLchar GLuint * len
void Check_Free(void)
free the mapbrush_t::nearBrushes, compositeSides and entitiesdef.h stuff.
#define LIGHTING_DAY_ONLY
bool AbortPrint(const verbosityLevel_t msgVerbLevel)
return nonzero if printing should be aborted based on the command line verbosity level and the import...
void Check_Stats(void)
print map stats on -stats
long WriteBSPFile(const char *filename)
Swaps the bsp file in place, so it should not be referenced again.
void CheckEntities(void)
Perform an entity check.
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...
void Verb_Printf(const verbosityLevel_t msgVerbLevel, const char *format,...)
decides wether to proceed with output based on verbosity level
struct usagePair_s usagePair_t
void Check_ContainedBrushes(void)
find duplicated brushes and brushes contained inside brushes
QGL_EXTERN int GLboolean GLfloat * v
void CheckFlagsBasedOnTextures(void)
sets content flags based on textures
void format(__printf__, 1, 2)))
void ExportLightmaps(const char *bspFileName)
Export the day and night lightmap and direction data for the given map.