1 /* -------------------------------------------------------------------------------
3 Copyright (C) 1999-2007 id Software, Inc. and contributors.
4 For a list of contributors, see the accompanying CONTRIBUTORS file.
6 This file is part of GtkRadiant.
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.
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.
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
22 ----------------------------------------------------------------------------------
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."
27 ------------------------------------------------------------------------------- */
46 #define SNAP_FLOAT_TO_INT 4
47 #define SNAP_INT_TO_FLOAT (1.0 / SNAP_FLOAT_TO_INT)
49 static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
61 fprintf( f, "\t// brush %d\n", num );
62 fprintf( f, "\t{\n" );
64 /* clear out build brush */
65 for( i = 0; i < buildBrush->numsides; i++ )
67 buildSide = &buildBrush->sides[ i ];
68 if( buildSide->winding != NULL )
70 FreeWinding( buildSide->winding );
71 buildSide->winding = NULL;
74 buildBrush->numsides = 0;
76 /* iterate through bsp brush sides */
77 for( i = 0; i < brush->numSides; i++ )
80 side = &bspBrushSides[ brush->firstSide + i ];
83 if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
85 shader = &bspShaders[ side->shaderNum ];
86 if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
90 plane = &bspPlanes[ side->planeNum ];
93 buildSide = &buildBrush->sides[ buildBrush->numsides ];
94 buildBrush->numsides++;
97 buildSide->shaderInfo = ShaderInfoForShader( shader->shader );
98 buildSide->planenum = side->planeNum;
99 buildSide->winding = NULL;
102 /* make brush windings */
103 if( !CreateBrushWindings( buildBrush ) )
106 /* iterate through build brush sides */
107 for( i = 0; i < buildBrush->numsides; i++ )
110 buildSide = &buildBrush->sides[ i ];
113 if( buildSide->shaderInfo == NULL || buildSide->winding == NULL )
116 /* get texture name */
117 if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
118 texture = buildSide->shaderInfo->shader + 9;
120 texture = buildSide->shaderInfo->shader;
122 /* get plane points and offset by origin */
123 for( j = 0; j < 3; j++ )
125 VectorAdd( buildSide->winding->p[ j ], origin, pts[ j ] );
126 //% pts[ j ][ 0 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 0 ] * SNAP_FLOAT_TO_INT + 0.5f );
127 //% pts[ j ][ 1 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 1 ] * SNAP_FLOAT_TO_INT + 0.5f );
128 //% pts[ j ][ 2 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 2 ] * SNAP_FLOAT_TO_INT + 0.5f );
131 /* print brush side */
132 /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
133 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",
134 pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
135 pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
136 pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
141 fprintf( f, "\t}\n\n" );
145 /* iterate through the brush sides (ignore the first 6 bevel planes) */
146 for( i = 0; i < brush->numSides; i++ )
149 side = &bspBrushSides[ brush->firstSide + i ];
152 if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
154 shader = &bspShaders[ side->shaderNum ];
155 if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
158 /* get texture name */
159 if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
160 texture = shader->shader + 9;
162 texture = shader->shader;
165 plane = &bspPlanes[ side->planeNum ];
167 /* make plane points */
172 MakeNormalVectors( plane->normal, vecs[ 0 ], vecs[ 1 ] );
173 VectorMA( vec3_origin, plane->dist, plane->normal, pts[ 0 ] );
174 VectorMA( pts[ 0 ], 256.0f, vecs[ 0 ], pts[ 1 ] );
175 VectorMA( pts[ 0 ], 256.0f, vecs[ 1 ], pts[ 2 ] );
178 /* offset by origin */
179 for( j = 0; j < 3; j++ )
180 VectorAdd( pts[ j ], origin, pts[ j ] );
182 /* print brush side */
183 /* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
184 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",
185 pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
186 pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
187 pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
196 converts a bsp patch to a map patch
204 ( ( 168 168 -192 0 2 ) ( 168 168 -64 0 1 ) ( 168 168 64 0 0 ) ... )
212 static void ConvertPatch( FILE *f, int num, bspDrawSurface_t *ds, vec3_t origin )
222 if( ds->surfaceType != MST_PATCH )
226 if( ds->shaderNum < 0 || ds->shaderNum >= numBSPShaders )
228 shader = &bspShaders[ ds->shaderNum ];
230 /* get texture name */
231 if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
232 texture = shader->shader + 9;
234 texture = shader->shader;
237 fprintf( f, "\t// patch %d\n", num );
238 fprintf( f, "\t{\n" );
239 fprintf( f, "\t\tpatchDef2\n" );
240 fprintf( f, "\t\t{\n" );
241 fprintf( f, "\t\t\t%s\n", texture );
242 fprintf( f, "\t\t\t( %d %d 0 0 0 )\n", ds->patchWidth, ds->patchHeight );
243 fprintf( f, "\t\t\t(\n" );
245 /* iterate through the verts */
246 for( x = 0; x < ds->patchWidth; x++ )
249 fprintf( f, "\t\t\t\t(" );
251 /* iterate through the row */
252 for( y = 0; y < ds->patchHeight; y++ )
255 dv = &bspDrawVerts[ ds->firstVert + (y * ds->patchWidth) + x ];
258 VectorAdd( origin, dv->xyz, xyz );
261 fprintf( f, " ( %f %f %f %f %f )", xyz[ 0 ], xyz[ 1 ], xyz[ 2 ], dv->st[ 0 ], dv->st[ 1 ] );
265 fprintf( f, " )\n" );
269 fprintf( f, "\t\t\t)\n" );
270 fprintf( f, "\t\t}\n" );
271 fprintf( f, "\t}\n\n" );
278 exports a bsp model to a map file
281 static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin )
285 bspDrawSurface_t *ds;
288 /* convert bsp planes to map planes */
289 nummapplanes = numBSPPlanes;
290 for( i = 0; i < numBSPPlanes; i++ )
292 VectorCopy( bspPlanes[ i ].normal, mapplanes[ i ].normal );
293 mapplanes[ i ].dist = bspPlanes[ i ].dist;
294 mapplanes[ i ].type = PlaneTypeForNormal( mapplanes[ i ].normal );
295 mapplanes[ i ].hash_chain = NULL;
298 /* allocate a build brush */
299 buildBrush = AllocBrush( 512 );
300 buildBrush->entityNum = 0;
301 buildBrush->original = buildBrush;
303 /* go through each brush in the model */
304 for( i = 0; i < model->numBSPBrushes; i++ )
306 num = i + model->firstBSPBrush;
307 brush = &bspBrushes[ num ];
308 ConvertBrush( f, num, brush, origin );
311 /* free the build brush */
314 /* go through each drawsurf in the model */
315 for( i = 0; i < model->numBSPSurfaces; i++ )
317 num = i + model->firstBSPSurface;
318 ds = &bspDrawSurfaces[ num ];
320 /* we only love patches */
321 if( ds->surfaceType == MST_PATCH )
322 ConvertPatch( f, num, ds, origin );
330 exports entity key/value pairs to a map file
333 static void ConvertEPairs( FILE *f, entity_t *e )
339 for( ep = e->epairs; ep != NULL; ep = ep->next )
341 /* ignore empty keys/values */
342 if( ep->key[ 0 ] == '\0' || ep->value[ 0 ] == '\0' )
345 /* ignore model keys with * prefixed values */
346 if( !Q_stricmp( ep->key, "model" ) && ep->value[ 0 ] == '*' )
350 fprintf( f, "\t\"%s\" \"%s\"\n", ep->key, ep->value );
358 exports an quake map file from the bsp
361 int ConvertBSPToMap( char *bspName )
369 char name[ 1024 ], base[ 1024 ];
373 Sys_Printf( "--- Convert BSP to MAP ---\n" );
375 /* create the bsp filename from the bsp name */
376 strcpy( name, bspName );
377 StripExtension( name );
378 strcat( name, "_converted.map" );
379 Sys_Printf( "writing %s\n", name );
381 ExtractFileBase( bspName, base );
382 strcat( base, ".bsp" );
385 f = fopen( name, "wb" );
387 Error( "Open failed on %s\n", name );
390 fprintf( f, "// Generated by Q3Map2 (ydnar) -convert -format map\n" );
392 /* walk entity list */
393 for( i = 0; i < numEntities; i++ )
399 fprintf( f, "// entity %d\n", i );
403 ConvertEPairs( f, e );
411 value = ValueForKey( e, "model" );
412 if( value[ 0 ] == '*' )
413 modelNum = atoi( value + 1 );
418 /* only handle bsp models */
422 model = &bspModels[ modelNum ];
424 /* get entity origin */
425 value = ValueForKey( e, "origin" );
426 if( value[ 0 ] == '\0' )
427 VectorClear( origin );
429 GetVectorForKey( e, "origin", origin );
432 ConvertModel( f, model, modelNum, origin );
436 fprintf( f, "}\n\n" );
439 /* close the file and return */
442 /* return to sender */