ufo2map.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 1997-2001 Id Software, Inc.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #define VERSION "1.2.5"
00027 #define REVISION "1"
00028 
00029 /* valid -nolighting parameters */
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     /* Do not change the -V output, you will break compile_maps.bat */
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     /* run through to find the length of the longest
00160      * flags string */
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 /* must be v->flags only, a full line not describing a flag */
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             /* arg to -v should be a single digit. if it is not a number
00235              * atoi will return 0, and no warning will be given. so check that
00236              * it looks like the arg for -v first */
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             /* make every point unique */
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             /* check for subparameters terminate loop before last arg (path) or
00250              * when we hit a param (as opposed to a subparam).
00251              * full parameters are prefixed with "-". */
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             /* if no subparams set, assume all */
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             /* Last param is the map path, every other param should have been caught by now. */
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     /* if any check or fix option is active then skip footsteps and materials */
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; /* bsp subdiv */
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; /* this value is up for debate blondandy */
00505 
00506     /* lightmap night values */
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     /* lightmap day values */
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     /* not up-to-date - recompile */
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     /* open the files */
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     /* This is done as two if statements to ensure that ftWriteMap and ftWriteBsp are populated first. */
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     /* init thread state */
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     /* if onlyents just grab the entities and resave */
00669     if (config.onlyents) {
00670         LoadBSPFile(bspFilename);
00671         num_entities = 0; /* use the map source entities */
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         /* level flags must be fixed before mixed face contents, or they swamp the
00686          * console with output, as levelflags are contentflags */
00687         if (config.chkLevelFlags || config.chkBrushes || config.chkAll)
00688             CheckLevelFlags();
00689         if (config.chkFillLevelFlags || config.chkBrushes || config.chkAll)
00690             CheckFillLevelFlags();
00691         /* this must be before mfc check, as otherwise mfc warnings are given
00692          * which are auto-fixed based on textures */
00693         if (config.chkTextures || config.chkBrushes || config.chkAll)
00694             CheckFlagsBasedOnTextures();
00695         /* mixed face contents check may remove contentflags. this should be done
00696          * before tex based on flags check, as tex may replace tex on the basis
00697          * of contentflags.*/
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         /* not included in bru or all by design */
00715         if (config.chkIntersection)
00716             Check_BrushIntersection();
00717 
00718         if (config.stats)
00719             Check_Stats();
00720 
00721         if (config.fixMap) {
00722             /* update dentdata */
00723             UnparseEntities();
00724             WriteMapFile(mapFilename);
00725         }
00726 
00727         /* the check stuff includes entitiesdef.h, which does not use mem.h.
00728          * this manual free is required */
00729         Check_Free();
00730 
00731         Mem_Shutdown();
00732 
00733         return 0;
00734     } else if (config.generateMaterialFile) {
00735         /* start from scratch */
00736         LoadMapFile(mapFilename);
00737         Mem_Shutdown();
00738         return 0;
00739     } else {
00740         /* start from scratch */
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             /* compile night version */
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             /* compile day version */
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         /* build per-vertex normals for phong shading */
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 }

Generated by  doxygen 1.6.2