00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #define VERSION "1.2.5"
00027 #define REVISION "1"
00028
00029
00030 #define LIGHTING_NONE 1
00031 #define LIGHTING_DAY_ONLY 2
00032 #define LIGHTING_NIGHT_ONLY 3
00033
00034 #if defined _WIN32
00035 # include <windows.h>
00036 #endif
00037
00038 #include "lighting.h"
00039 #include "bsp.h"
00040 #include "check/check.h"
00041 #include "check/checkentities.h"
00042 #include "check/checklib.h"
00043 #include "../../shared/shared.h"
00044 #include "ufo2map.h"
00045
00046 #ifdef HAVE_SYS_STAT_H
00047 #include <sys/stat.h>
00048 #endif
00049 #ifdef HAVE_SYS_TIME_H
00050 #include <sys/time.h>
00051 #endif
00052 #ifdef HAVE_SYS_RESOURCE_H
00053 #include <sys/resource.h>
00054 #endif
00055
00056 mapConfig_t config;
00057 static char mapFilename[MAX_OSPATH];
00058
00059 struct memPool_s *com_genericPool;
00060 struct memPool_s *com_fileSysPool;
00061
00062 char baseFilename[MAX_OSPATH];
00064 typedef struct usagePair_s {
00065 const char *flags;
00066 const char *desc;
00067 } usagePair_t;
00068
00069 static const usagePair_t usageArray[] = {
00070 {"Usage: ufo2map <param1 <subparam1> <subparam2> <...>> <param2> <...> [map]", NULL},
00071 #ifdef _WIN32
00072 {"Even on Windows, use / slashes in the path", NULL},
00073 #endif
00074 {"\nGeneral options:",NULL},
00075 {" -h --help", "print (this) help and exit"},
00076 #ifndef _WIN32
00077 {" -nice <prio>","priority level [unix nice level from -20 to 19 where 19 is the lowest priority]"},
00078 #else
00079 {" -nice <prio>","priority level [0 = HIGH, 1 = NORMAL, 2 = IDLE]"},
00080 #endif
00081 {" -nofootstep","don't generate a footstep file"},
00082 {" -tracefile","generate two csv files describing the floors and walls found by the trace functions"},
00083 {" -debugfile (TODO)","generate a trace debug file. The client can load the file to highlight map obstructions"},
00084 {" -onlynewer","only proceed when the map is newer than the bsp"},
00085 {" -stats --statistics","print statistics and quit. may be used with -check or -fix"},
00086 {" -v --verbosity <int>","set verbosity. higher <int> gives more output"},
00087 {NULL, "if it is required, this should be the first option"},
00088 {NULL, "0 - no stdout, 1 - only check/fix messages, 2 - (compile) only mapname"},
00089 {NULL, "2 - (check/fix) mapname if findings, 4 - normal output,"},
00090 {NULL, "5 - extra output, 6 - dump (a lot extra from BSPing)"},
00091
00092 {" -V --version","return Version and Revision level"},
00093 {" -material","generate a material (.mat) file, do not proceed to compilation"},
00094 {"\nLighting options:", NULL},
00095 {" -extra","extra light samples"},
00096 {" -nolighting TYPE","don't perform the lighting calculations, where TYPE is one of day, night, all"},
00097 {NULL, "default is all"},
00098 {" -quant","lightquant - lightmap resolution downscale (e.g. 4 = 1 << 4) (values between 1 and 6)"},
00099 {" -scale","global light scale factor"},
00100 {" -saturation","saturation factor (e.g. 1.5 - default is 1.0)"},
00101 {" -contrast","contrast factor (e.g. 1.05, default is 1.0)"},
00102 {" -t --threads","thread amount"},
00103 {"\nBinary space partitioning (BSPing) options:", NULL},
00104 {" -block <xl> <yl>",""},
00105 {" -blocks <xl> <yl> <xh> <yh>",""},
00106 {" -subdivide","subdivide brushes for better light effects (but higher polycount)"},
00107 {" -surface","surface light scaling (float value)"},
00108 {" -entity","entity light scaling (float value)"},
00109 {" -fulldetail","don't treat details (and trans surfaces) as details"},
00110 {" -info","print bsp file info"},
00111 {" -micro <float>","warn if a brush has a volume lower than the specified float."},
00112 {NULL, "brushes are tested after CSG."},
00113 {" -nobackclip","draw downward pointing faces. (so actors cannot see up through floors"},
00114 {NULL,"in first person view). default is to set SURF_NODRAW to downard faces."},
00115 {" -nocsg",""},
00116 {" -nodetail","skip detail brushes"},
00117 {" -nomerge","skip node face merging"},
00118 {" -noprune","don't prune (or cut) nodes"},
00119 {" -noshare",""},
00120 {" -notjunc",""},
00121 {" -nowater","skip water brushes in compilation"},
00122 {" -noweld",""},
00123 {" -onlyents","modify existing bsp file with entities from map file"},
00124 {" -exportlightmaps","write lightmaps into tga images"},
00125 {" -verboseentities","also be verbose about submodels (entities)"},
00126 {"\nMapping options:", NULL},
00127 {"\n These options operate on map file only. No bsp file is created.", NULL},
00128 {" Output prefixed by an asterisk (*) indicates operations that would change the map file.", NULL},
00129 {" -check","check source map, only print information."},
00130 {" -fix","same subparameters as -check, changes the source map file."},
00131 {" \n subparameters for -check and -fix", NULL},
00132 {" all","performs all checks and fixes. This is the default."},
00133 {" bru brushes","includes 'lvl tex mfc mbr'. Performs all checks and fixes associated with brushes."},
00134 {" ent entities","performs all checks and fixes associated with entities."},
00135 {" con contained","checks for brushes contained entirely within other brushes. includes coincident duplicates."},
00136 {" isc intersection","report intersection between optimisable brushes from worldspawn and func_group entities"},
00137 {NULL, "this is not included in all or bru as it is not always a bad thing"},
00138 {" mbr microbrush <float> ","test for brushes smaller than <float> unit^3. this is done without the csg"},
00139 {NULL, "step, unlike the bsp -micro option. default 1 unit^3."},
00140 {" lvl levelflags","if no levelflags for a brush or entity are set, all of them are set"},
00141 {" flv filllevelflags","ensure set levelflag bits are uninterrupted"},
00142 {" ndr nodraws","assigns SURF_NODRAW to hidden faces"},
00143 {" tex textures","warns when no texture or error texture is assigned."},
00144 {NULL, "ensures special textures and content/surface flags are consistent."},
00145 {" mfc mixedfacecontents","ensures the contentflags are the same on each face of each brush."},
00146 {" zft zfighting","intersecting brushes with a common face: prevent textures shimmering together"},
00147
00148 {NULL, NULL}
00149 };
00150
00154 static void Usage (void)
00155 {
00156 const usagePair_t *v;
00157 int maxFlagsLen = 0;
00158
00159
00160
00161 for (v = usageArray; v->flags || v->desc; v++)
00162 if (v->flags && v->desc) {
00163 const int len = strlen(v->flags);
00164 maxFlagsLen = len > maxFlagsLen ? len : maxFlagsLen;
00165 }
00166
00167 for (v = usageArray; v->flags || v->desc; v++) {
00168 if (v->flags && v->desc)
00169 Com_Printf("%-*s: %s\n", maxFlagsLen, v->flags, v->desc);
00170 else if (v->desc)
00171 Com_Printf("%*s %s\n", maxFlagsLen, "", v->desc);
00172 else
00173 Com_Printf("%s\n",v->flags);
00174 }
00175 }
00176
00180 void Com_Printf (const char *format, ...)
00181 {
00182 char out_buffer[4096];
00183 va_list argptr;
00184
00185 va_start(argptr, format);
00186 Q_vsnprintf(out_buffer, sizeof(out_buffer), format, argptr);
00187 va_end(argptr);
00188
00189 printf("%s", out_buffer);
00190 }
00191
00199 qboolean AbortPrint (const verbosityLevel_t msgVerbLevel)
00200 {
00201 return (msgVerbLevel > config.verbosity);
00202 }
00203
00208 void Verb_Printf (const verbosityLevel_t msgVerbLevel, const char *format, ...)
00209 {
00210 if (AbortPrint(msgVerbLevel))
00211 return;
00212
00213 {
00214 char out_buffer[4096];
00215 va_list argptr;
00216
00217 va_start(argptr, format);
00218 Q_vsnprintf(out_buffer, sizeof(out_buffer), format, argptr);
00219 va_end(argptr);
00220
00221 printf("%s", out_buffer);
00222 }
00223 }
00224
00228 static void U2M_Parameter (int argc, const char **argv)
00229 {
00230 int i;
00231
00232 for (i = 1; i < argc; i++) {
00233 if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "-verbosity")) {
00234
00235
00236
00237 if (strlen(argv[i+1]) == 1)
00238 config.verbosity = atoi(argv[++i]);
00239 Verb_Printf(VERB_LESS, "verbosity = %i\n", config.verbosity);
00240 } else if (!strcmp(argv[i], "-noweld")) {
00241
00242 Verb_Printf(VERB_LESS, "noweld = true\n");
00243 config.noweld = qtrue;
00244 } else if (!strcmp(argv[i], "--statistics") || !strcmp(argv[i], "-stats")) {
00245 Verb_Printf(VERB_LESS, "statistics mode\n");
00246 config.stats = qtrue;
00247 config.performMapCheck = qtrue;
00248 } else if (!strcmp(argv[i], "-check") || !strcmp(argv[i], "-fix")) {
00249
00250
00251
00252 const int iInitial = i;
00253
00254 if (!strcmp(argv[i], "-check")) {
00255 Verb_Printf(VERB_LESS, "check = true\n");
00256 config.performMapCheck = qtrue;
00257 }
00258 if (!strcmp(argv[i], "-fix")) {
00259 Verb_Printf(VERB_LESS, "fix = true\n");
00260 config.fixMap = qtrue;
00261 }
00262 while (++i < (argc - 1) && argv[i][0] != '-') {
00263 if (!strcmp(argv[i], "entities") || !strcmp(argv[i], "ent")) {
00264 Verb_Printf(VERB_LESS, " %s entities\n", config.fixMap ? "fixing" : "checking");
00265 config.chkEntities = qtrue;
00266 } else if (!strcmp(argv[i], "brushes") || !strcmp(argv[i], "bru")) {
00267 Verb_Printf(VERB_LESS, " %s brushes\n", config.fixMap ? "fixing" : "checking");
00268 config.chkBrushes = qtrue;
00269 } else if (!strcmp(argv[i], "contained") || !strcmp(argv[i], "con")) {
00270 Verb_Printf(VERB_LESS, " %s contained brushes\n", config.fixMap ? "fixing" : "checking");
00271 config.chkContained = qtrue;
00272 } else if (!strcmp(argv[i], "filllevelflags") || !strcmp(argv[i], "flv")) {
00273 Verb_Printf(VERB_LESS, " %s filllevelflags\n", config.fixMap ? "fixing" : "checking");
00274 config.chkFillLevelFlags = qtrue;
00275 } else if (!strcmp(argv[i], "levelflags") || !strcmp(argv[i], "lvl")) {
00276 Verb_Printf(VERB_LESS, " %s levelflags\n", config.fixMap ? "fixing" : "checking");
00277 config.chkLevelFlags = qtrue;
00278 } else if (!strcmp(argv[i], "textures") || !strcmp(argv[i], "tex")) {
00279 Verb_Printf(VERB_LESS, " %s textures\n", config.fixMap ? "fixing" : "checking");
00280 config.chkTextures = qtrue;
00281 } else if (!strcmp(argv[i], "nodraws") || !strcmp(argv[i], "ndr")) {
00282 Verb_Printf(VERB_LESS, " %s nodraws\n", config.fixMap ? "fixing" : "checking");
00283 config.chkNodraws = qtrue;
00284 } else if (!strcmp(argv[i], "intersection") || !strcmp(argv[i], "isc")) {
00285 Verb_Printf(VERB_LESS, " %s intersection\n", config.fixMap ? "fixing" : "checking");
00286 config.chkIntersection = qtrue;
00287 } else if (!strcmp(argv[i], "mixedfacecontents") || !strcmp(argv[i], "mfc")) {
00288 Verb_Printf(VERB_LESS, " %s mixedfacecontents\n", config.fixMap ? "fixing" : "checking");
00289 config.chkMixedFaceContents = qtrue;
00290 } else if (!strcmp(argv[i], "microbrush") || !strcmp(argv[i], "mbr")) {
00291 config.chkMMicro = qtrue;
00292 if (atof(argv[i + 1]) > 0.0001) {
00293 config.mapMicrovol = atof(argv[i + 1]);
00294 i++;
00295 }
00296 Verb_Printf(VERB_LESS, " checking map for microbrushes smaller than %f unit^3\n", config.mapMicrovol);
00297 } else if (!strcmp(argv[i], "zfighting") || !strcmp(argv[i], "zft")) {
00298 Verb_Printf(VERB_LESS, " %s for z-fighting\n", config.fixMap ? "fixing" : "checking");
00299 config.chkZFight = qtrue;
00300 } else if (!strcmp(argv[i], "all")) {
00301 Verb_Printf(VERB_LESS, " %s all (entites brushes)\n", config.fixMap ? "fixing" : "checking");
00302 config.chkAll = qtrue;
00303 } else {
00304 Verb_Printf(VERB_LESS, " WARNING: %s subparameter not understood:%s try --help for more info\n", config.fixMap ? "fix" : "check", argv[i]);
00305 }
00306 }
00307 i--;
00308
00309 if (i == iInitial) {
00310 Verb_Printf(VERB_LESS, " no %s subparameters set, assuming all\n", config.fixMap ? "fix" : "check");
00311 config.chkAll = qtrue;
00312 }
00313 } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
00314 Usage();
00315 exit(0);
00316 } else if (!strcmp(argv[i], "-t") || !strcmp(argv[i], "-threads")) {
00317 threadstate.numthreads = atoi(argv[++i]);
00318 Verb_Printf(VERB_LESS, "threads: #%i\n", threadstate.numthreads);
00319 } else if (!strcmp(argv[i], "-info")) {
00320 config.info = qtrue;
00321 } else if (!strcmp(argv[i], "-nocsg")) {
00322 Verb_Printf(VERB_LESS, "nocsg = true\n");
00323 config.nocsg = qtrue;
00324 } else if (!strcmp(argv[i], "-noshare")) {
00325 Verb_Printf(VERB_LESS, "noshare = true\n");
00326 config.noshare = qtrue;
00327 } else if (!strcmp(argv[i], "-onlynewer")) {
00328 Verb_Printf(VERB_LESS, "onlynewer = true\n");
00329 config.onlynewer = qtrue;
00330 } else if (!strcmp(argv[i], "-notjunc")) {
00331 Verb_Printf(VERB_LESS, "notjunc = true\n");
00332 config.notjunc = qtrue;
00333 } else if (!strcmp(argv[i], "-nowater")) {
00334 Verb_Printf(VERB_LESS, "nowater = true\n");
00335 config.nowater = qtrue;
00336 } else if (!strcmp(argv[i], "-nice")) {
00337 #ifdef HAVE_SETPRIORITY
00338 config.nice = atoi(argv[++i]);
00339 Verb_Printf(VERB_LESS, "nice = %i\n", config.nice);
00340 if (setpriority(PRIO_PROCESS, 0, config.nice))
00341 Verb_Printf(VERB_LESS, "failed to set nice level of %i\n", config.nice);
00342 #elif defined _WIN32
00343 HANDLE proc = GetCurrentProcess();
00344 config.nice = atoi(argv[++i]);
00345 Verb_Printf(VERB_LESS, "nice = %i\n", config.nice);
00346 switch (config.nice) {
00347 case 0:
00348 SetPriorityClass(proc, HIGH_PRIORITY_CLASS);
00349 Verb_Printf(VERB_LESS, "Priority changed to HIGH\n");
00350 break;
00351 case 1:
00352 SetPriorityClass(proc, NORMAL_PRIORITY_CLASS);
00353 Verb_Printf(VERB_LESS, "Priority changed to NORMAL\n");
00354 break;
00355 default:
00356 SetPriorityClass(proc, IDLE_PRIORITY_CLASS);
00357 Verb_Printf(VERB_LESS, "Priority changed to IDLE\n");
00358 break;
00359 }
00360 CloseHandle(proc);
00361 #else
00362 Verb_Printf(VERB_LESS, "nice not implemented for this arch\n");
00363 i++;
00364 #endif
00365 } else if (!strcmp(argv[i], "-noprune")) {
00366 Verb_Printf(VERB_LESS, "noprune = true\n");
00367 config.noprune = qtrue;
00368 } else if (!strcmp(argv[i],"-nofootstep")) {
00369 config.generateFootstepFile = qfalse;
00370 Verb_Printf(VERB_LESS, "generateFootstepFile = false\n");
00371 } else if (!strcmp(argv[i],"-tracefile")) {
00372 config.generateTraceFile = qtrue;
00373 Verb_Printf(VERB_NORMAL, "generateTraceFile = true\n");
00374 } else if (!strcmp(argv[i],"-debugtrace")) {
00375 config.generateDebugTrace = qtrue;
00376 Verb_Printf(VERB_NORMAL, "generateDebugTrace = true\n");
00377 } else if (!strcmp(argv[i],"-material")) {
00378 config.generateMaterialFile = qtrue;
00379 Verb_Printf(VERB_LESS, "generateMaterialFile = true\n");
00380 } else if (!strcmp(argv[i], "-nomerge")) {
00381 Verb_Printf(VERB_LESS, "nomerge = true\n");
00382 config.nomerge = qtrue;
00383 } else if (!strcmp(argv[i], "-nosubdiv")) {
00384 Verb_Printf(VERB_LESS, "nosubdiv = true\n");
00385 config.nosubdiv = qtrue;
00386 } else if (!strcmp(argv[i], "-nodetail")) {
00387 Verb_Printf(VERB_LESS, "nodetail = true\n");
00388 config.nodetail = qtrue;
00389 } else if (!strcmp(argv[i], "-fulldetail")) {
00390 Verb_Printf(VERB_LESS, "fulldetail = true\n");
00391 config.fulldetail = qtrue;
00392 } else if (!strcmp(argv[i], "-onlyents")) {
00393 Verb_Printf(VERB_LESS, "onlyents = true\n");
00394 config.onlyents = qtrue;
00395 } else if (!strcmp(argv[i], "-exportlightmaps")) {
00396 Verb_Printf(VERB_LESS, "exportlightmaps = true\n");
00397 config.exportLightmaps = qtrue;
00398 } else if (!strcmp(argv[i], "-micro")) {
00399 config.microvolume = atof(argv[i + 1]);
00400 Verb_Printf(VERB_LESS, "microvolume = %f\n", config.microvolume);
00401 i++;
00402 } else if (!strcmp(argv[i], "-verboseentities")) {
00403 Verb_Printf(VERB_LESS, "verboseentities = true\n");
00404 config.verboseentities = qtrue;
00405 } else if (!strcmp(argv[i], "-subdivide")) {
00406 config.subdivideSize = atof(argv[i + 1]);
00407 Verb_Printf(VERB_LESS, "subdivide_size = %f\n", config.subdivideSize);
00408 i++;
00409 } else if (!strcmp(argv[i], "-block")) {
00410 config.block_xl = config.block_xh = atoi(argv[i + 1]);
00411 config.block_yl = config.block_yh = atoi(argv[i + 2]);
00412 Verb_Printf(VERB_LESS, "block: %i,%i\n", config.block_xl, config.block_yl);
00413 i += 2;
00414 } else if (!strcmp(argv[i], "-blocks")) {
00415 config.block_xl = atoi(argv[i + 1]);
00416 config.block_yl = atoi(argv[i + 2]);
00417 config.block_xh = atoi(argv[i + 3]);
00418 config.block_yh = atoi(argv[i + 4]);
00419 Verb_Printf(VERB_LESS, "blocks: %i,%i to %i,%i\n",
00420 config.block_xl, config.block_yl, config.block_xh, config.block_yh);
00421 i += 4;
00422 } else if (!strcmp(argv[i], "-nobackclip")) {
00423 Verb_Printf(VERB_LESS, "nobackclip = true\n");
00424 config.nobackclip = qtrue;
00425 } else if (!strcmp(argv[i],"-extra")) {
00426 config.extrasamples = qtrue;
00427 Verb_Printf(VERB_LESS, "extrasamples = true\n");
00428 } else if (!strcmp(argv[i],"-quant")) {
00429 config.lightquant = (byte)atoi(argv[i + 1]);
00430 if (config.lightquant < 1 || config.lightquant > 6) {
00431 config.lightquant = 4;
00432 Verb_Printf(VERB_LESS, "lightquant must be between 1 and 6\n");
00433 }
00434 i++;
00435 } else if (!strcmp(argv[i],"-scale")) {
00436 config.brightness = atof(argv[i + 1]);
00437 i++;
00438 } else if (!strcmp(argv[i], "-saturation")) {
00439 config.saturation = atof(argv[i + 1]);
00440 Verb_Printf(VERB_LESS, "saturation at %f\n", config.saturation);
00441 i++;
00442 } else if (!strcmp(argv[i], "-contrast")) {
00443 config.contrast = atof(argv[i + 1]);
00444 Verb_Printf(VERB_LESS, "contrast at %f\n", config.contrast);
00445 i++;
00446 } else if (!strcmp(argv[i],"-surface")) {
00447 config.surface_scale *= atof(argv[i + 1]);
00448 Verb_Printf(VERB_LESS, "surface light scaling at %f\n", config.surface_scale);
00449 i++;
00450 } else if (!strcmp(argv[i],"-entity")) {
00451 config.entity_scale *= atof(argv[i + 1]);
00452 Verb_Printf(VERB_LESS, "entity light scaling at %f\n", config.entity_scale);
00453 i++;
00454 } else if (!strcmp(argv[i], "-nolighting")) {
00455 if (argc > i + 1) {
00456 if (!strcmp(argv[i + 1], "day")) {
00457 Verb_Printf(VERB_LESS, "nolighting = day\n");
00458 config.nolighting = LIGHTING_NIGHT_ONLY;
00459 i++;
00460 } else if (!strcmp(argv[i + 1], "night")) {
00461 Verb_Printf(VERB_LESS, "nolighting = night\n");
00462 config.nolighting = LIGHTING_DAY_ONLY;
00463 i++;
00464 } else {
00465 Verb_Printf(VERB_LESS, "nolighting = none\n");
00466 config.nolighting = LIGHTING_NONE;
00467 }
00468 } else {
00469 Sys_Error("invalid parameter count\n");
00470 }
00471 } else if (!strcmp(argv[i], "-V") || !strcmp(argv[i], "--version")) {
00472 Verb_Printf(VERB_LESS, "version:"VERSION" revision:"REVISION"\n");
00473 exit(0);
00474 } else if (i < (argc - 1)) {
00475
00476 Verb_Printf(VERB_LESS, "*** parameter not understood: %s try --help for more info\n", argv[i]);
00477 }
00478 }
00479
00480 if (config.fixMap && config.performMapCheck) {
00481 Sys_Error("do not specify both -fix and -check\n");
00482 }
00483
00484
00485 if (config.performMapCheck || config.fixMap) {
00486 config.generateFootstepFile = qfalse;
00487 config.generateMaterialFile = qfalse;
00488 }
00489 }
00490
00494 static void U2M_SetDefaultConfigValues (void)
00495 {
00496 config.verbosity = VERB_NORMAL;
00497
00498 config.subdivideSize = 1024.0f;
00499 config.block_xl = -8;
00500 config.block_xh = 7;
00501 config.block_yl = -8;
00502 config.block_yh = 7;
00503 config.microvolume = 1.0f;
00504 config.mapMicrovol = 1.0f;
00505
00506
00507 VectorSet(config.sun_ambient_color[LIGHTMAP_NIGHT], 0.07, 0.07, 0.08);
00508 config.sun_intensity[LIGHTMAP_NIGHT] = 70;
00509 Vector2Set(config.sun_angles[LIGHTMAP_NIGHT], -80, 220);
00510 VectorSet(config.sun_color[LIGHTMAP_NIGHT], 0.65, 0.75, 0.95);
00511 ColorNormalize(config.sun_color[LIGHTMAP_NIGHT], config.sun_color[LIGHTMAP_NIGHT]);
00512 AngleVectors(config.sun_angles[LIGHTMAP_NIGHT], config.sun_normal[LIGHTMAP_NIGHT], NULL, NULL);
00513
00514
00515 VectorSet(config.sun_ambient_color[LIGHTMAP_DAY], 0.26, 0.26, 0.26);
00516 config.sun_intensity[LIGHTMAP_DAY] = 280;
00517 Vector2Set(config.sun_angles[LIGHTMAP_DAY], -75, 100);
00518 VectorSet(config.sun_color[LIGHTMAP_DAY], 0.90, 0.75, 0.65);
00519 ColorNormalize(config.sun_color[LIGHTMAP_DAY], config.sun_color[LIGHTMAP_DAY]);
00520 AngleVectors(config.sun_angles[LIGHTMAP_DAY], config.sun_normal[LIGHTMAP_DAY], NULL, NULL);
00521
00522 config.saturation = 1.0f;
00523 config.contrast = 1.0f;
00524 config.brightness = 1.0;
00525 config.lightquant = 4;
00526 config.surface_scale = 0.4f;
00527 config.entity_scale = 1.0f;
00528
00529 config.generateFootstepFile = qtrue;
00530
00531 config.generateTraceFile = qfalse;
00532 config.generateDebugTrace = qfalse;
00533 }
00534
00535
00536 #ifdef HAVE_SYS_STAT_H
00537 static int CheckTimeDiff (const char *map, const char *bsp)
00538 {
00539 char buf[MAX_OSPATH];
00540 struct stat mapStat, bspStat;
00541
00542 snprintf(buf, sizeof(buf), "%s/%s", FS_Gamedir(), map);
00543 if (stat(buf, &mapStat) == -1)
00544 return 0;
00545 snprintf(buf, sizeof(buf), "%s/%s", FS_Gamedir(), bsp);
00546 if (stat(buf, &bspStat) == -1)
00547 return 0;
00548 if (difftime(mapStat.st_mtime, bspStat.st_mtime) < 0)
00549 return 1;
00550
00551 return 0;
00552 }
00553 #elif defined (_WIN32)
00554 static int CheckTimeDiff (const char *map, const char *bsp)
00555 {
00556 char buf[MAX_OSPATH];
00557 FILETIME ftCreate, ftAccess, ftWriteMap, ftWriteBsp;
00558 HANDLE hMapFile, hBspFile;
00559 int retval = 0;
00560
00561
00562 snprintf(buf, sizeof(buf), "%s/%s", FS_Gamedir(), map);
00563 hMapFile = CreateFile(buf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
00564 if (hMapFile == INVALID_HANDLE_VALUE)
00565 return 0;
00566 snprintf(buf, sizeof(buf), "%s/%s", FS_Gamedir(), bsp);
00567 hBspFile = CreateFile(buf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
00568 if (hBspFile == INVALID_HANDLE_VALUE){
00569 CloseHandle(hMapFile);
00570 return 0;
00571 }
00572
00573
00574 if (GetFileTime(hMapFile, &ftCreate, &ftAccess, &ftWriteMap)
00575 && GetFileTime(hBspFile, &ftCreate, &ftAccess, &ftWriteBsp)) {
00576 if (CompareFileTime(&ftWriteMap, &ftWriteBsp) == -1) {
00577 retval = 1;
00578 }
00579 }
00580
00581 CloseHandle(hMapFile);
00582 CloseHandle(hBspFile);
00583
00584 return retval;
00585 }
00586 #endif
00587
00592 void PrintMapName (void)
00593 {
00594 const char *mode = NULL;
00595
00596 if (config.performMapCheck) {
00597 mode = "[check]";
00598 } else if (config.fixMap) {
00599 mode = "[fix]";
00600 } else {
00601 mode = "[compile]";
00602 }
00603 Com_Printf("%s %s\n", mode, mapFilename);
00604 }
00605
00606
00607 int main (int argc, const char **argv)
00608 {
00609 char bspFilename[MAX_OSPATH];
00610 double begin, start, end;
00611 long size;
00612
00613 memset(&config, 0, sizeof(config));
00614
00615 memset(&threadstate, 0, sizeof(threadstate));
00616
00617 U2M_SetDefaultConfigValues();
00618
00619 U2M_Parameter(argc, argv);
00620
00621 Verb_Printf(VERB_NORMAL, "---- ufo2map "VERSION" ----\n");
00622
00623 if (argc < 2) {
00624 Usage();
00625 Sys_Error("At least provide 1 argument: the map filename.");
00626 }
00627
00628 Swap_Init();
00629 Mem_Init();
00630
00631 start = time(NULL);
00632
00633 com_genericPool = Mem_CreatePool("ufo2map");
00634 com_fileSysPool = Mem_CreatePool("ufo2map filesys");
00635
00636 Verb_Printf(VERB_NORMAL, "path: '%s'\n", argv[argc - 1]);
00637
00638 FS_InitFilesystem(qfalse);
00639
00640 Com_StripExtension(argv[argc - 1], mapFilename, sizeof(mapFilename));
00641 strncpy(baseFilename, mapFilename, sizeof(baseFilename) - 1);
00642 strncpy(bspFilename, mapFilename, sizeof(bspFilename) - 1);
00643 Com_DefaultExtension(mapFilename, sizeof(mapFilename), ".map");
00644 Com_DefaultExtension(bspFilename, sizeof(bspFilename), ".bsp");
00645
00646 if (config.info) {
00647 LoadBSPFile(bspFilename);
00648 PrintBSPFileSizes();
00649 Mem_Shutdown();
00650 return 0;
00651 }
00652
00653 Verb_Printf(VERB_NORMAL, "...map: '%s'\n", mapFilename);
00654 if (!(config.performMapCheck || config.fixMap))
00655 Verb_Printf(VERB_NORMAL, "...bsp: '%s'\n", bspFilename);
00656
00657 if (config.verbosity == VERB_MAPNAME && !(config.performMapCheck || config.fixMap))
00658 PrintMapName();
00659
00660 #if defined (HAVE_SYS_STAT_H) || defined (_WIN32)
00661 if (config.onlynewer && CheckTimeDiff(mapFilename, bspFilename)) {
00662 Verb_Printf(VERB_LESS, "bsp file is up-to-date\n");
00663 Mem_Shutdown();
00664 return 0;
00665 }
00666 #endif
00667
00668
00669 if (config.onlyents) {
00670 LoadBSPFile(bspFilename);
00671 num_entities = 0;
00672
00673 LoadMapFile(mapFilename);
00674 SetModelNumbers();
00675
00676 UnparseEntities();
00677
00678 WriteBSPFile(bspFilename);
00679 } else if (config.exportLightmaps) {
00680 LoadBSPFile(bspFilename);
00681 ExportLightmaps(bspFilename);
00682 size = 0;
00683 } else if (config.performMapCheck || config.fixMap) {
00684 LoadMapFile(mapFilename);
00685
00686
00687 if (config.chkLevelFlags || config.chkBrushes || config.chkAll)
00688 CheckLevelFlags();
00689 if (config.chkFillLevelFlags || config.chkBrushes || config.chkAll)
00690 CheckFillLevelFlags();
00691
00692
00693 if (config.chkTextures || config.chkBrushes || config.chkAll)
00694 CheckFlagsBasedOnTextures();
00695
00696
00697
00698 if (config.chkMixedFaceContents || config.chkBrushes || config.chkAll)
00699 CheckMixedFaceContents();
00700 if (config.chkTextures || config.chkBrushes || config.chkAll)
00701 CheckTexturesBasedOnFlags();
00702 if (config.chkMMicro || config.chkBrushes || config.chkAll)
00703 CheckMapMicro();
00704 if (config.chkContained || config.chkBrushes || config.chkAll)
00705 Check_ContainedBrushes();
00706 if (config.chkBrushes || config.chkAll)
00707 CheckBrushes();
00708 if (config.chkNodraws || config.chkAll)
00709 CheckNodraws();
00710 if (config.chkZFight || config.chkAll || config.chkBrushes)
00711 CheckZFighting();
00712 if (config.chkEntities || config.chkAll)
00713 CheckEntities();
00714
00715 if (config.chkIntersection)
00716 Check_BrushIntersection();
00717
00718 if (config.stats)
00719 Check_Stats();
00720
00721 if (config.fixMap) {
00722
00723 UnparseEntities();
00724 WriteMapFile(mapFilename);
00725 }
00726
00727
00728
00729 Check_Free();
00730
00731 Mem_Shutdown();
00732
00733 return 0;
00734 } else if (config.generateMaterialFile) {
00735
00736 LoadMapFile(mapFilename);
00737 Mem_Shutdown();
00738 return 0;
00739 } else {
00740
00741 LoadMapFile(mapFilename);
00742
00743 CheckNodraws();
00744 Check_Free();
00745
00746 SetModelNumbers();
00747
00748 ProcessModels(bspFilename);
00749 }
00750
00751 end = time(NULL);
00752 Verb_Printf(VERB_LESS, "%5.0f seconds elapsed\n", end - start);
00753 begin = start;
00754
00755 if (!config.exportLightmaps && !config.onlyents && config.nolighting != LIGHTING_NONE) {
00756 Verb_Printf(VERB_LESS, "----- Lighting ----\n");
00757
00758 CalcTextureReflectivity();
00759
00760 if (config.nolighting != LIGHTING_DAY_ONLY) {
00761
00762 start = time(NULL);
00763 LightWorld();
00764 end = time(NULL);
00765 Verb_Printf(VERB_LESS, "%5.0f seconds elapsed\n", end - start);
00766 }
00767
00768 if (config.nolighting != LIGHTING_NIGHT_ONLY) {
00769
00770 config.compile_for_day = 1;
00771 start = time(NULL);
00772 LightWorld();
00773 end = time(NULL);
00774 Verb_Printf(VERB_LESS, "%5.0f seconds elapsed\n", end - start);
00775 }
00776
00777 Verb_Printf(VERB_LESS, "writing %s\n", bspFilename);
00778 size = WriteBSPFile(bspFilename);
00779 } else if (!config.exportLightmaps) {
00780
00781 BuildVertexNormals();
00782 size = WriteBSPFile(bspFilename);
00783 end = time(NULL);
00784 }
00785
00786 Verb_Printf(VERB_LESS, "sum: %5.0f seconds elapsed - %.1g MB (%li bytes)\n\n", end - begin, (float)size / (1024.0f * 1024.0f), size);
00787
00788 Mem_Shutdown();
00789
00790 return 0;
00791 }