]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/convert_bsp.c
ac6270319527735677aed7ed0cb1fa6b1b6a0dc5
[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, const char *BSPFilePath, const char *surfaceFilePath ){
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, BSPFilePath, surfaceFilePath );
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         char BSPFilePath [ 1024 ];
142         char surfaceFilePath [ 1024 ];
143         qboolean map_allowed, force_bsp, force_map;
144
145
146         /* set default */
147         convertFunc = ConvertBSPToASE;
148         convertGame = NULL;
149         map_allowed = qfalse;
150         force_bsp = qfalse;
151         force_map = qfalse;
152
153         /* arg checking */
154         if ( argc < 1 ) {
155                 Sys_Printf( "Usage: q3map -convert [-format <ase|obj|map_bp|map>] [-shadersasbitmap|-lightmapsastexcoord|-deluxemapsastexcoord] [-readbsp|-readmap [-meta|-patchmeta]] [-v] <mapname>\n" );
156                 return 0;
157         }
158
159         /* process arguments */
160         for ( i = 1; i < ( argc - 1 ); i++ )
161         {
162                 /* -format map|ase|... */
163                 if ( !strcmp( argv[ i ],  "-format" ) ) {
164                         i++;
165                         if ( !Q_stricmp( argv[ i ], "ase" ) ) {
166                                 convertFunc = ConvertBSPToASE;
167                                 map_allowed = qfalse;
168                         }
169                         else if ( !Q_stricmp( argv[ i ], "obj" ) ) {
170                                 convertFunc = ConvertBSPToOBJ;
171                                 map_allowed = qfalse;
172                         }
173                         else if ( !Q_stricmp( argv[ i ], "map_bp" ) ) {
174                                 convertFunc = ConvertBSPToMap_BP;
175                                 map_allowed = qtrue;
176                         }
177                         else if ( !Q_stricmp( argv[ i ], "map" ) ) {
178                                 convertFunc = ConvertBSPToMap;
179                                 map_allowed = qtrue;
180                         }
181                         else
182                         {
183                                 convertGame = GetGame( argv[ i ] );
184                                 map_allowed = qfalse;
185                                 if ( convertGame == NULL ) {
186                                         Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
187                                 }
188                         }
189                 }
190                 else if ( !strcmp( argv[ i ],  "-ne" ) ) {
191                         normalEpsilon = atof( argv[ i + 1 ] );
192                         i++;
193                         Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
194                 }
195                 else if ( !strcmp( argv[ i ],  "-de" ) ) {
196                         distanceEpsilon = atof( argv[ i + 1 ] );
197                         i++;
198                         Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
199                 }
200                 else if ( !strcmp( argv[ i ],  "-shaderasbitmap" ) || !strcmp( argv[ i ],  "-shadersasbitmap" ) ) {
201                         shadersAsBitmap = qtrue;
202                 }
203                 else if ( !strcmp( argv[ i ],  "-lightmapastexcoord" ) || !strcmp( argv[ i ],  "-lightmapsastexcoord" ) ) {
204                         lightmapsAsTexcoord = qtrue;
205                 }
206                 else if ( !strcmp( argv[ i ],  "-deluxemapastexcoord" ) || !strcmp( argv[ i ],  "-deluxemapsastexcoord" ) ) {
207                         lightmapsAsTexcoord = qtrue;
208                         deluxemap = qtrue;
209                 }
210                 else if ( !strcmp( argv[ i ],  "-readbsp" ) ) {
211                         force_bsp = qtrue;
212                 }
213                 else if ( !strcmp( argv[ i ],  "-readmap" ) ) {
214                         force_map = qtrue;
215                 }
216                 else if ( !strcmp( argv[ i ],  "-meta" ) ) {
217                         meta = qtrue;
218                 }
219                 else if ( !strcmp( argv[ i ],  "-patchmeta" ) ) {
220                         meta = qtrue;
221                         patchMeta = qtrue;
222                 }
223         }
224
225         LoadShaderInfo();
226
227         /* clean up map name */
228         strcpy( source, ExpandArg( argv[i] ) );
229         ExtractFileExtension( source, ext );
230
231         if ( !map_allowed && !force_map ) {
232                 force_bsp = qtrue;
233         }
234
235         if ( force_map || ( !force_bsp && !Q_stricmp( ext, "map" ) && map_allowed ) ) {
236                 if ( !map_allowed ) {
237                         Sys_Printf( "WARNING: the requested conversion should not be done from .map files. Compile a .bsp first.\n" );
238                 }
239                 StripExtension( source );
240                 DefaultExtension( source, ".map" );
241                 Sys_Printf( "Loading %s\n", source );
242                 LoadMapFile( source, qfalse, convertGame == NULL );
243                 sprintf( BSPFilePath, "%s.bsp", source );
244                 sprintf( surfaceFilePath, "%s.srf", source );
245                 PseudoCompileBSP( convertGame != NULL, BSPFilePath, surfaceFilePath );
246         }
247         else
248         {
249                 StripExtension( source );
250                 DefaultExtension( source, ".bsp" );
251                 Sys_Printf( "Loading %s\n", source );
252                 LoadBSPFile( source );
253                 ParseEntities();
254         }
255
256         /* bsp format convert? */
257         if ( convertGame != NULL ) {
258                 /* set global game */
259                 game = convertGame;
260
261                 /* write bsp */
262                 StripExtension( source );
263                 DefaultExtension( source, "_c.bsp" );
264                 Sys_Printf( "Writing %s\n", source );
265                 WriteBSPFile( source );
266
267                 /* return to sender */
268                 return 0;
269         }
270
271         /* normal convert */
272         return convertFunc( source );
273 }