]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/main.c
transfer from internal tree r5311 branches/1.4-gpl
[xonotic/netradiant.git] / tools / quake3 / q3map2 / main.c
1 /*\r
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.\r
4 \r
5 This file is part of GtkRadiant.\r
6 \r
7 GtkRadiant is free software; you can redistribute it and/or modify\r
8 it under the terms of the GNU General Public License as published by\r
9 the Free Software Foundation; either version 2 of the License, or\r
10 (at your option) any later version.\r
11 \r
12 GtkRadiant is distributed in the hope that it will be useful,\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
15 GNU General Public License for more details.\r
16 \r
17 You should have received a copy of the GNU General Public License\r
18 along with GtkRadiant; if not, write to the Free Software\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
20 \r
21 -------------------------------------------------------------------------------\r
22 \r
23 This code has been altered significantly from its original form, to support\r
24 several games based on the Quake III Arena engine, in the form of "Q3Map2."\r
25 \r
26 ------------------------------------------------------------------------------- */\r
27 \r
28 \r
29 \r
30 /* marker */\r
31 #define MAIN_C\r
32 \r
33 \r
34 \r
35 /* dependencies */\r
36 #include "q3map2.h"\r
37 \r
38 \r
39 \r
40 /*\r
41 Random()\r
42 returns a pseudorandom number between 0 and 1\r
43 */\r
44 \r
45 vec_t Random( void )\r
46 {\r
47         return (vec_t) rand() / RAND_MAX;\r
48 }\r
49 \r
50 \r
51 \r
52 /*\r
53 ExitQ3Map()\r
54 cleanup routine\r
55 */\r
56 \r
57 static void ExitQ3Map( void )\r
58 {\r
59         BSPFilesCleanup();\r
60         if( mapDrawSurfs != NULL )\r
61                 free( mapDrawSurfs );\r
62 }\r
63 \r
64 \r
65 \r
66 /*\r
67 BSPInfo()\r
68 emits statistics about the bsp file\r
69 */\r
70 \r
71 int BSPInfo( int count, char **fileNames )\r
72 {\r
73         int                     i;\r
74         char            source[ 1024 ], ext[ 64 ];\r
75         int                     size;\r
76         FILE            *f;\r
77         \r
78         \r
79         /* dummy check */\r
80         if( count < 1 )\r
81         {\r
82                 Sys_Printf( "No files to dump info for.\n");\r
83                 return -1;\r
84         }\r
85         \r
86         /* enable info mode */\r
87         infoMode = qtrue;\r
88         \r
89         /* walk file list */\r
90         for( i = 0; i < count; i++ )\r
91         {\r
92                 Sys_Printf( "---------------------------------\n" );\r
93                 \r
94                 /* mangle filename and get size */\r
95                 strcpy( source, fileNames[ i ] );\r
96                 ExtractFileExtension( source, ext );\r
97                 if( !Q_stricmp( ext, "map" ) )\r
98                         StripExtension( source );\r
99                 DefaultExtension( source, ".bsp" );\r
100                 f = fopen( source, "rb" );\r
101                 if( f )\r
102                 {\r
103                         size = Q_filelength (f);\r
104                         fclose( f );\r
105                 }\r
106                 else\r
107                         size = 0;\r
108                 \r
109                 /* load the bsp file and print lump sizes */\r
110                 Sys_Printf( "%s\n", source );\r
111                 LoadBSPFile( source );          \r
112                 PrintBSPFileSizes();\r
113                 \r
114                 /* print sizes */\r
115                 Sys_Printf( "\n" );\r
116                 Sys_Printf( "          total         %9d\n", size );\r
117                 Sys_Printf( "                        %9d KB\n", size / 1024 );\r
118                 Sys_Printf( "                        %9d MB\n", size / (1024 * 1024) );\r
119                 \r
120                 Sys_Printf( "---------------------------------\n" );\r
121         }\r
122         \r
123         /* return count */\r
124         return i;\r
125 }\r
126 \r
127 \r
128 \r
129 /*\r
130 ScaleBSPMain()\r
131 amaze and confuse your enemies with wierd scaled maps!\r
132 */\r
133 \r
134 int ScaleBSPMain( int argc, char **argv )\r
135 {\r
136         int                     i;\r
137         float           f, scale;\r
138         vec3_t          vec;\r
139         char            str[ 1024 ];\r
140         \r
141         \r
142         /* arg checking */\r
143         if( argc < 2 )\r
144         {\r
145                 Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );\r
146                 return 0;\r
147         }\r
148         \r
149         /* get scale */\r
150         scale = atof( argv[ argc - 2 ] );\r
151         if( scale == 0.0f )\r
152         {\r
153                 Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );\r
154                 Sys_Printf( "Non-zero scale value required.\n" );\r
155                 return 0;\r
156         }\r
157         \r
158         /* do some path mangling */\r
159         strcpy( source, ExpandArg( argv[ argc - 1 ] ) );\r
160         StripExtension( source );\r
161         DefaultExtension( source, ".bsp" );\r
162         \r
163         /* load the bsp */\r
164         Sys_Printf( "Loading %s\n", source );\r
165         LoadBSPFile( source );\r
166         ParseEntities();\r
167         \r
168         /* note it */\r
169         Sys_Printf( "--- ScaleBSP ---\n" );\r
170         Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );\r
171         \r
172         /* scale entity keys */\r
173         for( i = 0; i < numBSPEntities && i < numEntities; i++ )\r
174         {\r
175                 /* scale origin */\r
176                 GetVectorForKey( &entities[ i ], "origin", vec );\r
177                 if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) )\r
178                 {\r
179                         VectorScale( vec, scale, vec );\r
180                         sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );\r
181                         SetKeyValue( &entities[ i ], "origin", str );\r
182                 }\r
183                 \r
184                 /* scale door lip */\r
185                 f = FloatForKey( &entities[ i ], "lip" );\r
186                 if( f )\r
187                 {\r
188                         f *= scale;\r
189                         sprintf( str, "%f", f );\r
190                         SetKeyValue( &entities[ i ], "lip", str );\r
191                 }\r
192         }\r
193         \r
194         /* scale models */\r
195         for( i = 0; i < numBSPModels; i++ )\r
196         {\r
197                 VectorScale( bspModels[ i ].mins, scale, bspModels[ i ].mins );\r
198                 VectorScale( bspModels[ i ].maxs, scale, bspModels[ i ].maxs );\r
199         }\r
200         \r
201         /* scale nodes */\r
202         for( i = 0; i < numBSPNodes; i++ )\r
203         {\r
204                 VectorScale( bspNodes[ i ].mins, scale, bspNodes[ i ].mins );\r
205                 VectorScale( bspNodes[ i ].maxs, scale, bspNodes[ i ].maxs );\r
206         }\r
207         \r
208         /* scale leafs */\r
209         for( i = 0; i < numBSPLeafs; i++ )\r
210         {\r
211                 VectorScale( bspLeafs[ i ].mins, scale, bspLeafs[ i ].mins );\r
212                 VectorScale( bspLeafs[ i ].maxs, scale, bspLeafs[ i ].maxs );\r
213         }\r
214         \r
215         /* scale drawverts */\r
216         for( i = 0; i < numBSPDrawVerts; i++ )\r
217                 VectorScale( bspDrawVerts[ i ].xyz, scale, bspDrawVerts[ i ].xyz );\r
218         \r
219         /* scale planes */\r
220         for( i = 0; i < numBSPPlanes; i++ )\r
221                 bspPlanes[ i ].dist *= scale;\r
222         \r
223         /* scale gridsize */\r
224         GetVectorForKey( &entities[ 0 ], "gridsize", vec );\r
225         if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) == 0.0f )\r
226                 VectorCopy( gridSize, vec );\r
227         VectorScale( vec, scale, vec );\r
228         sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );\r
229         SetKeyValue( &entities[ 0 ], "gridsize", str );\r
230         \r
231         /* write the bsp */\r
232         UnparseEntities();\r
233         StripExtension( source );\r
234         DefaultExtension( source, "_s.bsp" );\r
235         Sys_Printf( "Writing %s\n", source );\r
236         WriteBSPFile( source );\r
237         \r
238         /* return to sender */\r
239         return 0;\r
240 }\r
241 \r
242 \r
243 \r
244 /*\r
245 ConvertBSPMain()\r
246 main argument processing function for bsp conversion\r
247 */\r
248 \r
249 int ConvertBSPMain( int argc, char **argv )\r
250 {\r
251         int             i;\r
252         int             (*convertFunc)( char * );\r
253         \r
254         \r
255         /* set default */\r
256         convertFunc = ConvertBSPToASE;\r
257         \r
258         /* arg checking */\r
259         if( argc < 1 )\r
260         {\r
261                 Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );\r
262                 return 0;\r
263         }\r
264         \r
265         /* process arguments */\r
266         for( i = 1; i < (argc - 1); i++ )\r
267         {\r
268                 /* -format map|ase|... */\r
269                 if( !strcmp( argv[ i ],  "-format" ) )\r
270                 {\r
271                         i++;\r
272                         if( !Q_stricmp( argv[ i ], "ase" ) )\r
273                                 convertFunc = ConvertBSPToASE;\r
274                         else if( !Q_stricmp( argv[ i ], "map" ) )\r
275                                 convertFunc = ConvertBSPToMap;\r
276                         else\r
277                                 Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );\r
278                 }\r
279         }\r
280         \r
281         /* clean up map name */\r
282         strcpy( source, ExpandArg( argv[ i ] ) );\r
283         StripExtension( source );\r
284         DefaultExtension( source, ".bsp" );\r
285         \r
286         LoadShaderInfo();\r
287         \r
288         Sys_Printf( "Loading %s\n", source );\r
289         \r
290         /* ydnar: load surface file */\r
291         //%     LoadSurfaceExtraFile( source );\r
292         \r
293         LoadBSPFile( source );\r
294         \r
295         /* parse bsp entities */\r
296         ParseEntities();\r
297         \r
298         /* convert */\r
299         return convertFunc( source );\r
300 }\r
301 \r
302 \r
303 \r
304 /*\r
305 main()\r
306 q3map mojo...\r
307 */\r
308 \r
309 int main( int argc, char **argv )\r
310 {\r
311         int             i, r;\r
312         double  start, end;\r
313         \r
314         \r
315         /* we want consistent 'randomness' */\r
316         srand( 0 );\r
317         \r
318         /* start timer */\r
319         start = I_FloatTime();\r
320 \r
321         /* this was changed to emit version number over the network */\r
322         printf( Q3MAP_VERSION "\n" );\r
323         \r
324         /* set exit call */\r
325         atexit( ExitQ3Map );\r
326         \r
327         /* read general options first */\r
328         for( i = 1; i < argc; i++ )\r
329         {\r
330                 /* -connect */\r
331                 if( !strcmp( argv[ i ], "-connect" ) )\r
332                 {\r
333                         argv[ i ] = NULL;\r
334                         i++;\r
335                         Broadcast_Setup( argv[ i ] );\r
336                         argv[ i ] = NULL;\r
337                 }\r
338                 \r
339                 /* verbose */\r
340                 else if( !strcmp( argv[ i ], "-v" ) )\r
341                 {\r
342                         verbose = qtrue;\r
343                         argv[ i ] = NULL;\r
344                 }\r
345                 \r
346                 /* force */\r
347                 else if( !strcmp( argv[ i ], "-force" ) )\r
348                 {\r
349                         force = qtrue;\r
350                         argv[ i ] = NULL;\r
351                 }\r
352                 \r
353                 /* patch subdivisions */\r
354                 else if( !strcmp( argv[ i ], "-subdivisions" ) )\r
355                 {\r
356                         argv[ i ] = NULL;\r
357                         i++;\r
358                         patchSubdivisions = atoi( argv[ i ] );\r
359                         argv[ i ] = NULL;\r
360                         if( patchSubdivisions <= 0 )\r
361                                 patchSubdivisions = 1;\r
362                 }\r
363                 \r
364                 /* threads */\r
365                 else if( !strcmp( argv[ i ], "-threads" ) )\r
366                 {\r
367                         argv[ i ] = NULL;\r
368                         i++;\r
369                         numthreads = atoi( argv[ i ] );\r
370                         argv[ i ] = NULL;\r
371                 }\r
372         }\r
373         \r
374         /* init model library */\r
375         PicoInit();\r
376         PicoSetMallocFunc( safe_malloc );\r
377         PicoSetFreeFunc( free );\r
378         PicoSetPrintFunc( PicoPrintFunc );\r
379         PicoSetLoadFileFunc( PicoLoadFileFunc );\r
380         PicoSetFreeFileFunc( free );\r
381         \r
382         /* set number of threads */\r
383         ThreadSetDefault();\r
384         \r
385         /* generate sinusoid jitter table */\r
386         for( i = 0; i < MAX_JITTERS; i++ )\r
387         {\r
388                 jitters[ i ] = sin( i * 139.54152147 );\r
389                 //%     Sys_Printf( "Jitter %4d: %f\n", i, jitters[ i ] );\r
390         }\r
391         \r
392         /* we print out two versions, q3map's main version (since it evolves a bit out of GtkRadiant)\r
393            and we put the GtkRadiant version to make it easy to track with what version of Radiant it was built with */\r
394         \r
395         Sys_Printf( "Q3Map         - v1.0r (c) 1999 Id Software Inc.\n" );\r
396         Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );\r
397         Sys_Printf( "GtkRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );\r
398         Sys_Printf( "%s\n", Q3MAP_MOTD );\r
399         \r
400         /* ydnar: new path initialization */\r
401         InitPaths( &argc, argv );\r
402         \r
403         /* check if we have enough options left to attempt something */\r
404         if( argc < 2 )\r
405                 Error( "Usage: %s [general options] [options] mapfile", argv[ 0 ] );\r
406         \r
407         /* info */\r
408         if( !strcmp( argv[ 1 ], "-info" ) )\r
409                 r = BSPInfo( argc - 2, argv + 2 );\r
410         \r
411         /* vis */\r
412         else if( !strcmp( argv[ 1 ], "-vis" ) )\r
413                 r = VisMain( argc - 1, argv + 1 );\r
414         \r
415         /* light */\r
416         else if( !strcmp( argv[ 1 ], "-light" ) )\r
417                 r = LightMain( argc - 1, argv + 1 );\r
418         \r
419         /* vlight */\r
420         else if( !strcmp( argv[ 1 ], "-vlight" ) )\r
421         {\r
422                 Sys_Printf( "WARNING: VLight is no longer supported, defaulting to -light -fast instead\n\n" );\r
423                 argv[ 1 ] = "-fast";    /* eek a hack */\r
424                 r = LightMain( argc, argv );\r
425         }\r
426         \r
427         /* ydnar: lightmap export */\r
428         else if( !strcmp( argv[ 1 ], "-export" ) )\r
429                 r = ExportLightmapsMain( argc - 1, argv + 1 );\r
430         \r
431         /* ydnar: lightmap import */\r
432         else if( !strcmp( argv[ 1 ], "-import" ) )\r
433                 r = ImportLightmapsMain( argc - 1, argv + 1 );\r
434         \r
435         /* ydnar: bsp scaling */\r
436         else if( !strcmp( argv[ 1 ], "-scale" ) )\r
437                 r = ScaleBSPMain( argc - 1, argv + 1 );\r
438         \r
439         /* ydnar: bsp conversion */\r
440         else if( !strcmp( argv[ 1 ], "-convert" ) )\r
441                 r = ConvertBSPMain( argc - 1, argv + 1 );\r
442         \r
443         /* ydnar: otherwise create a bsp */\r
444         else\r
445                 r = BSPMain( argc, argv );\r
446         \r
447         /* emit time */\r
448         end = I_FloatTime();\r
449         Sys_Printf( "%9.0f seconds elapsed\n", end - start );\r
450         \r
451         /* shut down connection */\r
452         Broadcast_Shutdown();\r
453         \r
454         /* return any error code */\r
455         return r;\r
456 }\r