split bsp analyze/info/scale stuff from q3map2
[xonotic/netradiant.git] / tools / quake3 / q3map2 / convert_bsp.c
1 /* -------------------------------------------------------------------------------
2
3    Copyright (C) 1999-2007 id Software, Inc. and contributors.
4    For a list of contributors, see the accompanying CONTRIBUTORS file.
5
6    This file is part of GtkRadiant.
7
8    GtkRadiant is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12
13    GtkRadiant is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with GtkRadiant; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21
22    -------------------------------------------------------------------------------
23
24    This code has been altered significantly from its original form, to support
25    several games based on the Quake III Arena engine, in the form of "Q3Map2."
26
27    ------------------------------------------------------------------------------- */
28
29
30
31 /* dependencies */
32 #include "q3map2.h"
33
34
35
36 /*
37    PseudoCompileBSP()
38    a stripped down ProcessModels
39  */
40 void PseudoCompileBSP( qboolean need_tree ){
41         int models;
42         char modelValue[10];
43         entity_t *entity;
44         face_t *faces;
45         tree_t *tree;
46         node_t *node;
47         brush_t *brush;
48         side_t *side;
49         int i;
50
51         SetDrawSurfacesBuffer();
52         mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
53         memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
54         numMapDrawSurfs = 0;
55
56         BeginBSPFile();
57         models = 1;
58         for ( mapEntityNum = 0; mapEntityNum < numEntities; mapEntityNum++ )
59         {
60                 /* get entity */
61                 entity = &entities[ mapEntityNum ];
62                 if ( entity->brushes == NULL && entity->patches == NULL ) {
63                         continue;
64                 }
65
66                 if ( mapEntityNum != 0 ) {
67                         sprintf( modelValue, "*%d", models++ );
68                         SetKeyValue( entity, "model", modelValue );
69                 }
70
71                 /* process the model */
72                 Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels );
73                 BeginModel();
74
75                 entity->firstDrawSurf = numMapDrawSurfs;
76
77                 ClearMetaTriangles();
78                 PatchMapDrawSurfs( entity );
79
80                 if ( mapEntityNum == 0 && need_tree ) {
81                         faces = MakeStructuralBSPFaceList( entities[0].brushes );
82                         tree = FaceBSP( faces );
83                         node = tree->headnode;
84                 }
85                 else
86                 {
87                         node = AllocNode();
88                         node->planenum = PLANENUM_LEAF;
89                         tree = AllocTree();
90                         tree->headnode = node;
91                 }
92
93                 /* a minimized ClipSidesIntoTree */
94                 for ( brush = entity->brushes; brush; brush = brush->next )
95                 {
96                         /* walk the brush sides */
97                         for ( i = 0; i < brush->numsides; i++ )
98                         {
99                                 /* get side */
100                                 side = &brush->sides[ i ];
101                                 if ( side->winding == NULL ) {
102                                         continue;
103                                 }
104                                 /* shader? */
105                                 if ( side->shaderInfo == NULL ) {
106                                         continue;
107                                 }
108                                 /* save this winding as a visible surface */
109                                 DrawSurfaceForSide( entity, brush, side, side->winding );
110                         }
111                 }
112
113                 if ( meta ) {
114                         ClassifyEntitySurfaces( entity );
115                         MakeEntityDecals( entity );
116                         MakeEntityMetaTriangles( entity );
117                         SmoothMetaTriangles();
118                         MergeMetaTriangles();
119                 }
120                 FilterDrawsurfsIntoTree( entity, tree );
121
122                 FilterStructuralBrushesIntoTree( entity, tree );
123                 FilterDetailBrushesIntoTree( entity, tree );
124
125                 EmitBrushes( entity->brushes, &entity->firstBrush, &entity->numBrushes );
126                 EndModel( entity, node );
127         }
128         EndBSPFile( qfalse );
129 }
130
131 /*
132    ConvertBSPMain()
133    main argument processing function for bsp conversion
134  */
135
136 int ConvertBSPMain( int argc, char **argv ){
137         int i;
138         int ( *convertFunc )( char * );
139         game_t  *convertGame;
140         char ext[1024];
141         qboolean map_allowed, force_bsp, force_map;
142
143
144         /* set default */
145         convertFunc = ConvertBSPToASE;
146         convertGame = NULL;
147         map_allowed = qfalse;
148         force_bsp = qfalse;
149         force_map = qfalse;
150
151         /* arg checking */
152         if ( argc < 1 ) {
153                 Sys_Printf( "Usage: q3map -convert [-format <ase|obj|map_bp|map>] [-shadersasbitmap|-lightmapsastexcoord|-deluxemapsastexcoord] [-readbsp|-readmap [-meta|-patchmeta]] [-v] <mapname>\n" );
154                 return 0;
155         }
156
157         /* process arguments */
158         for ( i = 1; i < ( argc - 1 ); i++ )
159         {
160                 /* -format map|ase|... */
161                 if ( !strcmp( argv[ i ],  "-format" ) ) {
162                         i++;
163                         if ( !Q_stricmp( argv[ i ], "ase" ) ) {
164                                 convertFunc = ConvertBSPToASE;
165                                 map_allowed = qfalse;
166                         }
167                         else if ( !Q_stricmp( argv[ i ], "obj" ) ) {
168                                 convertFunc = ConvertBSPToOBJ;
169                                 map_allowed = qfalse;
170                         }
171                         else if ( !Q_stricmp( argv[ i ], "map_bp" ) ) {
172                                 convertFunc = ConvertBSPToMap_BP;
173                                 map_allowed = qtrue;
174                         }
175                         else if ( !Q_stricmp( argv[ i ], "map" ) ) {
176                                 convertFunc = ConvertBSPToMap;
177                                 map_allowed = qtrue;
178                         }
179                         else
180                         {
181                                 convertGame = GetGame( argv[ i ] );
182                                 map_allowed = qfalse;
183                                 if ( convertGame == NULL ) {
184                                         Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
185                                 }
186                         }
187                 }
188                 else if ( !strcmp( argv[ i ],  "-ne" ) ) {
189                         normalEpsilon = atof( argv[ i + 1 ] );
190                         i++;
191                         Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
192                 }
193                 else if ( !strcmp( argv[ i ],  "-de" ) ) {
194                         distanceEpsilon = atof( argv[ i + 1 ] );
195                         i++;
196                         Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
197                 }
198                 else if ( !strcmp( argv[ i ],  "-shaderasbitmap" ) || !strcmp( argv[ i ],  "-shadersasbitmap" ) ) {
199                         shadersAsBitmap = qtrue;
200                 }
201                 else if ( !strcmp( argv[ i ],  "-lightmapastexcoord" ) || !strcmp( argv[ i ],  "-lightmapsastexcoord" ) ) {
202                         lightmapsAsTexcoord = qtrue;
203                 }
204                 else if ( !strcmp( argv[ i ],  "-deluxemapastexcoord" ) || !strcmp( argv[ i ],  "-deluxemapsastexcoord" ) ) {
205                         lightmapsAsTexcoord = qtrue;
206                         deluxemap = qtrue;
207                 }
208                 else if ( !strcmp( argv[ i ],  "-readbsp" ) ) {
209                         force_bsp = qtrue;
210                 }
211                 else if ( !strcmp( argv[ i ],  "-readmap" ) ) {
212                         force_map = qtrue;
213                 }
214                 else if ( !strcmp( argv[ i ],  "-meta" ) ) {
215                         meta = qtrue;
216                 }
217                 else if ( !strcmp( argv[ i ],  "-patchmeta" ) ) {
218                         meta = qtrue;
219                         patchMeta = qtrue;
220                 }
221         }
222
223         LoadShaderInfo();
224
225         /* clean up map name */
226         strcpy( source, ExpandArg( argv[i] ) );
227         ExtractFileExtension( source, ext );
228
229         if ( !map_allowed && !force_map ) {
230                 force_bsp = qtrue;
231         }
232
233         if ( force_map || ( !force_bsp && !Q_stricmp( ext, "map" ) && map_allowed ) ) {
234                 if ( !map_allowed ) {
235                         Sys_Printf( "WARNING: the requested conversion should not be done from .map files. Compile a .bsp first.\n" );
236                 }
237                 StripExtension( source );
238                 DefaultExtension( source, ".map" );
239                 Sys_Printf( "Loading %s\n", source );
240                 LoadMapFile( source, qfalse, convertGame == NULL );
241                 PseudoCompileBSP( convertGame != NULL );
242         }
243         else
244         {
245                 StripExtension( source );
246                 DefaultExtension( source, ".bsp" );
247                 Sys_Printf( "Loading %s\n", source );
248                 LoadBSPFile( source );
249                 ParseEntities();
250         }
251
252         /* bsp format convert? */
253         if ( convertGame != NULL ) {
254                 /* set global game */
255                 game = convertGame;
256
257                 /* write bsp */
258                 StripExtension( source );
259                 DefaultExtension( source, "_c.bsp" );
260                 Sys_Printf( "Writing %s\n", source );
261                 WriteBSPFile( source );
262
263                 /* return to sender */
264                 return 0;
265         }
266
267         /* normal convert */
268         return convertFunc( source );
269 }