]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/convert_map.c
set eol-style
[xonotic/netradiant.git] / tools / quake3 / q3map2 / convert_map.c
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
21 ----------------------------------------------------------------------------------
22
23 This code has been altered significantly from its original form, to support
24 several games based on the Quake III Arena engine, in the form of "Q3Map2."
25
26 ------------------------------------------------------------------------------- */
27
28
29
30 /* marker */
31 #define CONVERT_MAP_C
32
33
34
35 /* dependencies */
36 #include "q3map2.h"
37
38
39
40 /*
41 ConvertBrush()
42 exports a map brush
43 */
44
45 #define SNAP_FLOAT_TO_INT       4
46 #define SNAP_INT_TO_FLOAT       (1.0 / SNAP_FLOAT_TO_INT)
47
48 static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
49 {
50         int                             i, j;
51         bspBrushSide_t  *side;
52         side_t                  *buildSide;
53         bspShader_t             *shader;
54         char                    *texture;
55         bspPlane_t              *plane;
56         vec3_t                  pts[ 3 ];
57         
58         
59         /* start brush */
60         fprintf( f, "\t// brush %d\n", num );
61         fprintf( f, "\t{\n" );
62         
63         /* clear out build brush */
64         for( i = 0; i < buildBrush->numsides; i++ )
65         {
66                 buildSide = &buildBrush->sides[ i ];
67                 if( buildSide->winding != NULL )
68                 {
69                         FreeWinding( buildSide->winding );
70                         buildSide->winding = NULL;
71                 }
72         }
73         buildBrush->numsides = 0;
74         
75         /* iterate through bsp brush sides */
76         for( i = 0; i < brush->numSides; i++ )
77         {
78                 /* get side */
79                 side = &bspBrushSides[ brush->firstSide + i ];
80                 
81                 /* get shader */
82                 if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
83                         continue;
84                 shader = &bspShaders[ side->shaderNum ];
85                 if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
86                         continue;
87                 
88                 /* get plane */
89                 plane = &bspPlanes[ side->planeNum ];
90                 
91                 /* add build side */
92                 buildSide = &buildBrush->sides[ buildBrush->numsides ];
93                 buildBrush->numsides++;
94                 
95                 /* tag it */
96                 buildSide->shaderInfo = ShaderInfoForShader( shader->shader );
97                 buildSide->planenum = side->planeNum;
98                 buildSide->winding = NULL;
99         }
100         
101         /* make brush windings */
102         if( !CreateBrushWindings( buildBrush ) )
103                 return;
104         
105         /* iterate through build brush sides */
106         for( i = 0; i < buildBrush->numsides; i++ )
107         {
108                 /* get build side */
109                 buildSide = &buildBrush->sides[ i ];
110                 
111                 /* dummy check */
112                 if( buildSide->shaderInfo == NULL || buildSide->winding == NULL )
113                         continue;
114                 
115                 /* get texture name */
116                 if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
117                         texture = buildSide->shaderInfo->shader + 9;
118                 else
119                         texture = buildSide->shaderInfo->shader;
120                 
121                 /* get plane points and offset by origin */
122                 for( j = 0; j < 3; j++ )
123                 {
124                         VectorAdd( buildSide->winding->p[ j ], origin, pts[ j ] );
125                         //%     pts[ j ][ 0 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 0 ] * SNAP_FLOAT_TO_INT + 0.5f );
126                         //%     pts[ j ][ 1 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 1 ] * SNAP_FLOAT_TO_INT + 0.5f );
127                         //%     pts[ j ][ 2 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 2 ] * SNAP_FLOAT_TO_INT + 0.5f );
128                 }
129                 
130                 /* print brush side */
131                 /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
132                 fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) %s 0 0 0 0.5 0.5 0 0 0\n",
133                         pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
134                         pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
135                         pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
136                         texture );
137         }
138         
139         /* end brush */
140         fprintf( f, "\t}\n\n" );
141 }
142
143 #if 0
144         /* iterate through the brush sides (ignore the first 6 bevel planes) */
145         for( i = 0; i < brush->numSides; i++ )
146         {
147                 /* get side */
148                 side = &bspBrushSides[ brush->firstSide + i ];
149                 
150                 /* get shader */
151                 if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
152                         continue;
153                 shader = &bspShaders[ side->shaderNum ];
154                 if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
155                         continue;
156                 
157                 /* get texture name */
158                 if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
159                         texture = shader->shader + 9;
160                 else
161                         texture = shader->shader;
162                 
163                 /* get plane */
164                 plane = &bspPlanes[ side->planeNum ];
165
166                 /* make plane points */
167                 {
168                         vec3_t  vecs[ 2 ];
169
170                         
171                         MakeNormalVectors( plane->normal, vecs[ 0 ], vecs[ 1 ] );
172                         VectorMA( vec3_origin, plane->dist, plane->normal, pts[ 0 ] );
173                         VectorMA( pts[ 0 ], 256.0f, vecs[ 0 ], pts[ 1 ] );
174                         VectorMA( pts[ 0 ], 256.0f, vecs[ 1 ], pts[ 2 ] );
175                 }
176
177                 /* offset by origin */
178                 for( j = 0; j < 3; j++ )
179                         VectorAdd( pts[ j ], origin, pts[ j ] );
180                 
181                 /* print brush side */
182                 /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
183                 fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) %s 0 0 0 0.5 0.5 0 0 0\n",
184                         pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
185                         pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
186                         pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
187                         texture );
188         }
189 #endif
190
191
192
193 /*
194 ConvertPatch()
195 converts a bsp patch to a map patch
196
197         {
198                 patchDef2
199                 {
200                         base_wall/concrete
201                         ( 9 3 0 0 0 )
202                         (
203                                 ( ( 168 168 -192 0 2 ) ( 168 168 -64 0 1 ) ( 168 168 64 0 0 ) ... )
204                                 ...
205                         )
206                 }
207         }
208
209 */
210
211 static void ConvertPatch( FILE *f, int num, bspDrawSurface_t *ds, vec3_t origin )
212 {
213         int                             x, y;
214         bspShader_t             *shader;
215         char                    *texture;
216         bspDrawVert_t   *dv;
217         vec3_t                  xyz;
218         
219         
220         /* only patches */
221         if( ds->surfaceType != MST_PATCH )
222                 return;
223         
224         /* get shader */
225         if( ds->shaderNum < 0 || ds->shaderNum >= numBSPShaders )
226                 return;
227         shader = &bspShaders[ ds->shaderNum ];
228         
229         /* get texture name */
230         if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
231                 texture = shader->shader + 9;
232         else
233                 texture = shader->shader;
234         
235         /* start patch */
236         fprintf( f, "\t// patch %d\n", num );
237         fprintf( f, "\t{\n" );
238         fprintf( f, "\t\tpatchDef2\n" );
239         fprintf( f, "\t\t{\n" );
240         fprintf( f, "\t\t\t%s\n", texture );
241         fprintf( f, "\t\t\t( %d %d 0 0 0 )\n", ds->patchWidth, ds->patchHeight );
242         fprintf( f, "\t\t\t(\n" );
243         
244         /* iterate through the verts */
245         for( x = 0; x < ds->patchWidth; x++ )
246         {
247                 /* start row */
248                 fprintf( f, "\t\t\t\t(" );
249                 
250                 /* iterate through the row */
251                 for( y = 0; y < ds->patchHeight; y++ )
252                 {
253                         /* get vert */
254                         dv = &bspDrawVerts[ ds->firstVert + (y * ds->patchWidth) + x ];
255                         
256                         /* offset it */
257                         VectorAdd( origin, dv->xyz, xyz );
258                         
259                         /* print vertex */
260                         fprintf( f, " ( %f %f %f %f %f )", xyz[ 0 ], xyz[ 1 ], xyz[ 2 ], dv->st[ 0 ], dv->st[ 1 ] );
261                 }
262                 
263                 /* end row */
264                 fprintf( f, " )\n" );
265         }
266         
267         /* end patch */
268         fprintf( f, "\t\t\t)\n" );
269         fprintf( f, "\t\t}\n" );
270         fprintf( f, "\t}\n\n" );
271 }
272
273
274
275 /*
276 ConvertModel()
277 exports a bsp model to a map file
278 */
279
280 static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin )
281 {
282         int                                     i, num;
283         bspBrush_t                      *brush;
284         bspDrawSurface_t        *ds;
285         
286         
287         /* convert bsp planes to map planes */
288         nummapplanes = numBSPPlanes;
289         for( i = 0; i < numBSPPlanes; i++ )
290         {
291                 VectorCopy( bspPlanes[ i ].normal, mapplanes[ i ].normal );
292                 mapplanes[ i ].dist = bspPlanes[ i ].dist;
293                 mapplanes[ i ].type = PlaneTypeForNormal( mapplanes[ i ].normal );
294                 mapplanes[ i ].hash_chain = NULL;
295         }
296         
297         /* allocate a build brush */
298         buildBrush = AllocBrush( 512 );
299         buildBrush->entityNum = 0;
300         buildBrush->original = buildBrush;
301         
302         /* go through each brush in the model */
303         for( i = 0; i < model->numBSPBrushes; i++ )
304         {
305                 num = i + model->firstBSPBrush;
306                 brush = &bspBrushes[ num ];
307                 ConvertBrush( f, num, brush, origin );
308         }
309         
310         /* free the build brush */
311         free( buildBrush );
312         
313         /* go through each drawsurf in the model */
314         for( i = 0; i < model->numBSPSurfaces; i++ )
315         {
316                 num = i + model->firstBSPSurface;
317                 ds = &bspDrawSurfaces[ num ];
318                 
319                 /* we only love patches */
320                 if( ds->surfaceType == MST_PATCH )
321                         ConvertPatch( f, num, ds, origin );
322         }
323 }
324
325
326
327 /*
328 ConvertEPairs()
329 exports entity key/value pairs to a map file
330 */
331
332 static void ConvertEPairs( FILE *f, entity_t *e )
333 {
334         epair_t *ep;
335         
336         
337         /* walk epairs */
338         for( ep = e->epairs; ep != NULL; ep = ep->next )
339         {
340                 /* ignore empty keys/values */
341                 if( ep->key[ 0 ] == '\0' || ep->value[ 0 ] == '\0' )
342                         continue;
343
344                 /* ignore model keys with * prefixed values */
345                 if( !Q_stricmp( ep->key, "model" ) && ep->value[ 0 ] == '*' )
346                         continue;
347                 
348                 /* emit the epair */
349                 fprintf( f, "\t\"%s\" \"%s\"\n", ep->key, ep->value );
350         }
351 }
352
353
354
355 /*
356 ConvertBSPToMap()
357 exports an quake map file from the bsp
358 */
359
360 int ConvertBSPToMap( char *bspName )
361 {
362         int                             i, modelNum;
363         FILE                    *f;
364         bspModel_t              *model;
365         entity_t                *e;
366         vec3_t                  origin;
367         const char              *value;
368         char                    name[ 1024 ], base[ 1024 ];
369         
370         
371         /* note it */
372         Sys_Printf( "--- Convert BSP to MAP ---\n" );
373         
374         /* create the bsp filename from the bsp name */
375         strcpy( name, bspName );
376         StripExtension( name );
377         strcat( name, "_converted.map" );
378         Sys_Printf( "writing %s\n", name );
379         
380         ExtractFileBase( bspName, base );
381         strcat( base, ".bsp" );
382         
383         /* open it */
384         f = fopen( name, "wb" );
385         if( f == NULL )
386                 Error( "Open failed on %s\n", name );
387         
388         /* print header */
389         fprintf( f, "// Generated by Q3Map2 (ydnar) -convert -format map\n" );
390         
391         /* walk entity list */
392         for( i = 0; i < numEntities; i++ )
393         {
394                 /* get entity */
395                 e = &entities[ i ];
396                 
397                 /* start entity */
398                 fprintf( f, "// entity %d\n", i );
399                 fprintf( f, "{\n" );
400                 
401                 /* export keys */
402                 ConvertEPairs( f, e );
403                 fprintf( f, "\n" );
404                 
405                 /* get model num */
406                 if( i == 0 )
407                         modelNum = 0;
408                 else
409                 {
410                         value = ValueForKey( e, "model" );
411                         if( value[ 0 ] == '*' )
412                                 modelNum = atoi( value + 1 );
413                         else
414                                 modelNum = -1;
415                 }
416                 
417                 /* only handle bsp models */
418                 if( modelNum >= 0 )
419                 {
420                         /* get model */
421                         model = &bspModels[ modelNum ];
422                         
423                         /* get entity origin */
424                         value = ValueForKey( e, "origin" );
425                         if( value[ 0 ] == '\0' )
426                                 VectorClear( origin );
427                         else
428                                 GetVectorForKey( e, "origin", origin );
429                         
430                         /* convert model */
431                         ConvertModel( f, model, modelNum, origin );
432                 }
433                 
434                 /* end entity */
435                 fprintf( f, "}\n\n" );
436         }
437         
438         /* close the file and return */
439         fclose( f );
440         
441         /* return to sender */
442         return 0;
443 }