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