2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
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.
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.
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
21 ----------------------------------------------------------------------------------
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."
26 ------------------------------------------------------------------------------- */
45 #define SNAP_FLOAT_TO_INT 4
46 #define SNAP_INT_TO_FLOAT (1.0 / SNAP_FLOAT_TO_INT)
48 static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
60 fprintf( f, "\t// brush %d\n", num );
61 fprintf( f, "\t{\n" );
63 /* clear out build brush */
64 for( i = 0; i < buildBrush->numsides; i++ )
66 buildSide = &buildBrush->sides[ i ];
67 if( buildSide->winding != NULL )
69 FreeWinding( buildSide->winding );
70 buildSide->winding = NULL;
73 buildBrush->numsides = 0;
75 /* iterate through bsp brush sides */
76 for( i = 0; i < brush->numSides; i++ )
79 side = &bspBrushSides[ brush->firstSide + i ];
82 if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
84 shader = &bspShaders[ side->shaderNum ];
85 if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
89 plane = &bspPlanes[ side->planeNum ];
92 buildSide = &buildBrush->sides[ buildBrush->numsides ];
93 buildBrush->numsides++;
96 buildSide->shaderInfo = ShaderInfoForShader( shader->shader );
97 buildSide->planenum = side->planeNum;
98 buildSide->winding = NULL;
101 /* make brush windings */
102 if( !CreateBrushWindings( buildBrush ) )
105 /* iterate through build brush sides */
106 for( i = 0; i < buildBrush->numsides; i++ )
109 buildSide = &buildBrush->sides[ i ];
112 if( buildSide->shaderInfo == NULL || buildSide->winding == NULL )
115 /* get texture name */
116 if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
117 texture = buildSide->shaderInfo->shader + 9;
119 texture = buildSide->shaderInfo->shader;
121 /* get plane points and offset by origin */
122 for( j = 0; j < 3; j++ )
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 );
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 ],
140 fprintf( f, "\t}\n\n" );
144 /* iterate through the brush sides (ignore the first 6 bevel planes) */
145 for( i = 0; i < brush->numSides; i++ )
148 side = &bspBrushSides[ brush->firstSide + i ];
151 if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
153 shader = &bspShaders[ side->shaderNum ];
154 if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
157 /* get texture name */
158 if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
159 texture = shader->shader + 9;
161 texture = shader->shader;
164 plane = &bspPlanes[ side->planeNum ];
166 /* make plane points */
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 ] );
177 /* offset by origin */
178 for( j = 0; j < 3; j++ )
179 VectorAdd( pts[ j ], origin, pts[ j ] );
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 ],
195 converts a bsp patch to a map patch
203 ( ( 168 168 -192 0 2 ) ( 168 168 -64 0 1 ) ( 168 168 64 0 0 ) ... )
211 static void ConvertPatch( FILE *f, int num, bspDrawSurface_t *ds, vec3_t origin )
221 if( ds->surfaceType != MST_PATCH )
225 if( ds->shaderNum < 0 || ds->shaderNum >= numBSPShaders )
227 shader = &bspShaders[ ds->shaderNum ];
229 /* get texture name */
230 if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
231 texture = shader->shader + 9;
233 texture = shader->shader;
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" );
244 /* iterate through the verts */
245 for( x = 0; x < ds->patchWidth; x++ )
248 fprintf( f, "\t\t\t\t(" );
250 /* iterate through the row */
251 for( y = 0; y < ds->patchHeight; y++ )
254 dv = &bspDrawVerts[ ds->firstVert + (y * ds->patchWidth) + x ];
257 VectorAdd( origin, dv->xyz, xyz );
260 fprintf( f, " ( %f %f %f %f %f )", xyz[ 0 ], xyz[ 1 ], xyz[ 2 ], dv->st[ 0 ], dv->st[ 1 ] );
264 fprintf( f, " )\n" );
268 fprintf( f, "\t\t\t)\n" );
269 fprintf( f, "\t\t}\n" );
270 fprintf( f, "\t}\n\n" );
277 exports a bsp model to a map file
280 static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin )
284 bspDrawSurface_t *ds;
287 /* convert bsp planes to map planes */
288 nummapplanes = numBSPPlanes;
289 for( i = 0; i < numBSPPlanes; i++ )
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;
297 /* allocate a build brush */
298 buildBrush = AllocBrush( 512 );
299 buildBrush->entityNum = 0;
300 buildBrush->original = buildBrush;
302 /* go through each brush in the model */
303 for( i = 0; i < model->numBSPBrushes; i++ )
305 num = i + model->firstBSPBrush;
306 brush = &bspBrushes[ num ];
307 ConvertBrush( f, num, brush, origin );
310 /* free the build brush */
313 /* go through each drawsurf in the model */
314 for( i = 0; i < model->numBSPSurfaces; i++ )
316 num = i + model->firstBSPSurface;
317 ds = &bspDrawSurfaces[ num ];
319 /* we only love patches */
320 if( ds->surfaceType == MST_PATCH )
321 ConvertPatch( f, num, ds, origin );
329 exports entity key/value pairs to a map file
332 static void ConvertEPairs( FILE *f, entity_t *e )
338 for( ep = e->epairs; ep != NULL; ep = ep->next )
340 /* ignore empty keys/values */
341 if( ep->key[ 0 ] == '\0' || ep->value[ 0 ] == '\0' )
344 /* ignore model keys with * prefixed values */
345 if( !Q_stricmp( ep->key, "model" ) && ep->value[ 0 ] == '*' )
349 fprintf( f, "\t\"%s\" \"%s\"\n", ep->key, ep->value );
357 exports an quake map file from the bsp
360 int ConvertBSPToMap( char *bspName )
368 char name[ 1024 ], base[ 1024 ];
372 Sys_Printf( "--- Convert BSP to MAP ---\n" );
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 );
380 ExtractFileBase( bspName, base );
381 strcat( base, ".bsp" );
384 f = fopen( name, "wb" );
386 Error( "Open failed on %s\n", name );
389 fprintf( f, "// Generated by Q3Map2 (ydnar) -convert -format map\n" );
391 /* walk entity list */
392 for( i = 0; i < numEntities; i++ )
398 fprintf( f, "// entity %d\n", i );
402 ConvertEPairs( f, e );
410 value = ValueForKey( e, "model" );
411 if( value[ 0 ] == '*' )
412 modelNum = atoi( value + 1 );
417 /* only handle bsp models */
421 model = &bspModels[ modelNum ];
423 /* get entity origin */
424 value = ValueForKey( e, "origin" );
425 if( value[ 0 ] == '\0' )
426 VectorClear( origin );
428 GetVectorForKey( e, "origin", origin );
431 ConvertModel( f, model, modelNum, origin );
435 fprintf( f, "}\n\n" );
438 /* close the file and return */
441 /* return to sender */