1 /* -------------------------------------------------------------------------------
2
3 Copyright (C) 1999-2006 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
ConvertBrush(FILE * f,int num,bspBrush_t * brush,vec3_t origin)49 static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
50 {
51 int i, j;
52 bspBrushSide_t *side;
53 side_t *buildSide;
54 bspShader_t *shader;
55 char *texture;
56 bspPlane_t *plane;
57 vec3_t pts[ 3 ];
58
59
60 /* start brush */
61 fprintf( f, "\t// brush %d\n", num );
62 fprintf( f, "\t{\n" );
63
64 /* clear out build brush */
65 for( i = 0; i < buildBrush->numsides; i++ )
66 {
67 buildSide = &buildBrush->sides[ i ];
68 if( buildSide->winding != NULL )
69 {
70 FreeWinding( buildSide->winding );
71 buildSide->winding = NULL;
72 }
73 }
74 buildBrush->numsides = 0;
75
76 /* iterate through bsp brush sides */
77 for( i = 0; i < brush->numSides; i++ )
78 {
79 /* get side */
80 side = &bspBrushSides[ brush->firstSide + i ];
81
82 /* get shader */
83 if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
84 continue;
85 shader = &bspShaders[ side->shaderNum ];
86 if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
87 continue;
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 /* iterate through build brush sides */
107 for( i = 0; i < buildBrush->numsides; i++ )
108 {
109 /* get build side */
110 buildSide = &buildBrush->sides[ i ];
111
112 /* dummy check */
113 if( buildSide->shaderInfo == NULL || buildSide->winding == NULL )
114 continue;
115
116 /* get texture name */
117 if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
118 texture = buildSide->shaderInfo->shader + 9;
119 else
120 texture = buildSide->shaderInfo->shader;
121
122 /* get plane points and offset by origin */
123 for( j = 0; j < 3; j++ )
124 {
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 );
129 }
130
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 ],
137 texture );
138 }
139
140 /* end brush */
141 fprintf( f, "\t}\n\n" );
142 }
143
144 #if 0
145 /* iterate through the brush sides (ignore the first 6 bevel planes) */
146 for( i = 0; i < brush->numSides; i++ )
147 {
148 /* get side */
149 side = &bspBrushSides[ brush->firstSide + i ];
150
151 /* get shader */
152 if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
153 continue;
154 shader = &bspShaders[ side->shaderNum ];
155 if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
156 continue;
157
158 /* get texture name */
159 if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
160 texture = shader->shader + 9;
161 else
162 texture = shader->shader;
163
164 /* get plane */
165 plane = &bspPlanes[ side->planeNum ];
166
167 /* make plane points */
168 {
169 vec3_t vecs[ 2 ];
170
171
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 ] );
176 }
177
178 /* offset by origin */
179 for( j = 0; j < 3; j++ )
180 VectorAdd( pts[ j ], origin, pts[ j ] );
181
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 ],
188 texture );
189 }
190 #endif
191
192
193
194 /*
195 ConvertPatch()
196 converts a bsp patch to a map patch
197
198 {
199 patchDef2
200 {
201 base_wall/concrete
202 ( 9 3 0 0 0 )
203 (
204 ( ( 168 168 -192 0 2 ) ( 168 168 -64 0 1 ) ( 168 168 64 0 0 ) ... )
205 ...
206 )
207 }
208 }
209
210 */
211
ConvertPatch(FILE * f,int num,bspDrawSurface_t * ds,vec3_t origin)212 static void ConvertPatch( FILE *f, int num, bspDrawSurface_t *ds, vec3_t origin )
213 {
214 int x, y;
215 bspShader_t *shader;
216 char *texture;
217 bspDrawVert_t *dv;
218 vec3_t xyz;
219
220
221 /* only patches */
222 if( ds->surfaceType != MST_PATCH )
223 return;
224
225 /* get shader */
226 if( ds->shaderNum < 0 || ds->shaderNum >= numBSPShaders )
227 return;
228 shader = &bspShaders[ ds->shaderNum ];
229
230 /* get texture name */
231 if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
232 texture = shader->shader + 9;
233 else
234 texture = shader->shader;
235
236 /* start patch */
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" );
244
245 /* iterate through the verts */
246 for( x = 0; x < ds->patchWidth; x++ )
247 {
248 /* start row */
249 fprintf( f, "\t\t\t\t(" );
250
251 /* iterate through the row */
252 for( y = 0; y < ds->patchHeight; y++ )
253 {
254 /* get vert */
255 dv = &bspDrawVerts[ ds->firstVert + (y * ds->patchWidth) + x ];
256
257 /* offset it */
258 VectorAdd( origin, dv->xyz, xyz );
259
260 /* print vertex */
261 fprintf( f, " ( %f %f %f %f %f )", xyz[ 0 ], xyz[ 1 ], xyz[ 2 ], dv->st[ 0 ], dv->st[ 1 ] );
262 }
263
264 /* end row */
265 fprintf( f, " )\n" );
266 }
267
268 /* end patch */
269 fprintf( f, "\t\t\t)\n" );
270 fprintf( f, "\t\t}\n" );
271 fprintf( f, "\t}\n\n" );
272 }
273
274
275
276 /*
277 ConvertModel()
278 exports a bsp model to a map file
279 */
280
ConvertModel(FILE * f,bspModel_t * model,int modelNum,vec3_t origin)281 static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin )
282 {
283 int i, num;
284 bspBrush_t *brush;
285 bspDrawSurface_t *ds;
286
287
288 /* convert bsp planes to map planes */
289 nummapplanes = numBSPPlanes;
290 for( i = 0; i < numBSPPlanes; i++ )
291 {
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;
296 }
297
298 /* allocate a build brush */
299 buildBrush = AllocBrush( 512 );
300 buildBrush->entityNum = 0;
301 buildBrush->original = buildBrush;
302
303 /* go through each brush in the model */
304 for( i = 0; i < model->numBSPBrushes; i++ )
305 {
306 num = i + model->firstBSPBrush;
307 brush = &bspBrushes[ num ];
308 ConvertBrush( f, num, brush, origin );
309 }
310
311 /* free the build brush */
312 free( buildBrush );
313
314 /* go through each drawsurf in the model */
315 for( i = 0; i < model->numBSPSurfaces; i++ )
316 {
317 num = i + model->firstBSPSurface;
318 ds = &bspDrawSurfaces[ num ];
319
320 /* we only love patches */
321 if( ds->surfaceType == MST_PATCH )
322 ConvertPatch( f, num, ds, origin );
323 }
324 }
325
326
327
328 /*
329 ConvertEPairs()
330 exports entity key/value pairs to a map file
331 */
332
ConvertEPairs(FILE * f,entity_t * e)333 static void ConvertEPairs( FILE *f, entity_t *e )
334 {
335 epair_t *ep;
336
337
338 /* walk epairs */
339 for( ep = e->epairs; ep != NULL; ep = ep->next )
340 {
341 /* ignore empty keys/values */
342 if( ep->key[ 0 ] == '\0' || ep->value[ 0 ] == '\0' )
343 continue;
344
345 /* ignore model keys with * prefixed values */
346 if( !Q_stricmp( ep->key, "model" ) && ep->value[ 0 ] == '*' )
347 continue;
348
349 /* emit the epair */
350 fprintf( f, "\t\"%s\" \"%s\"\n", ep->key, ep->value );
351 }
352 }
353
354
355
356 /*
357 ConvertBSPToMap()
358 exports an quake map file from the bsp
359 */
360
ConvertBSPToMap(char * bspName)361 int ConvertBSPToMap( char *bspName )
362 {
363 int i, modelNum;
364 FILE *f;
365 bspModel_t *model;
366 entity_t *e;
367 vec3_t origin;
368 const char *value;
369 char name[ 1024 ], base[ 1024 ];
370
371
372 /* note it */
373 Sys_Printf( "--- Convert BSP to MAP ---\n" );
374
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 );
380
381 ExtractFileBase( bspName, base );
382 strcat( base, ".bsp" );
383
384 /* open it */
385 f = fopen( name, "wb" );
386 if( f == NULL )
387 Error( "Open failed on %s\n", name );
388
389 /* print header */
390 fprintf( f, "// Generated by Q3Map2 (ydnar) -convert -format map\n" );
391
392 /* walk entity list */
393 for( i = 0; i < numEntities; i++ )
394 {
395 /* get entity */
396 e = &entities[ i ];
397
398 /* start entity */
399 fprintf( f, "// entity %d\n", i );
400 fprintf( f, "{\n" );
401
402 /* export keys */
403 ConvertEPairs( f, e );
404 fprintf( f, "\n" );
405
406 /* get model num */
407 if( i == 0 )
408 modelNum = 0;
409 else
410 {
411 value = ValueForKey( e, "model" );
412 if( value[ 0 ] == '*' )
413 modelNum = atoi( value + 1 );
414 else
415 modelNum = -1;
416 }
417
418 /* only handle bsp models */
419 if( modelNum >= 0 )
420 {
421 /* get model */
422 model = &bspModels[ modelNum ];
423
424 /* get entity origin */
425 value = ValueForKey( e, "origin" );
426 if( value[ 0 ] == '\0' )
427 VectorClear( origin );
428 else
429 GetVectorForKey( e, "origin", origin );
430
431 /* convert model */
432 ConvertModel( f, model, modelNum, origin );
433 }
434
435 /* end entity */
436 fprintf( f, "}\n\n" );
437 }
438
439 /* close the file and return */
440 fclose( f );
441
442 /* return to sender */
443 return 0;
444 }
445