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