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 BSPFILE_IBSP_C
33 
34 
35 
36 /* dependencies */
37 #include "q3map2.h"
38 
39 
40 
41 
42 /* -------------------------------------------------------------------------------
43 
44 this file handles translating the bsp file format used by quake 3, rtcw, and ef
45 into the abstracted bsp file used by q3map2.
46 
47 ------------------------------------------------------------------------------- */
48 
49 /* constants */
50 #define	LUMP_ENTITIES		0
51 #define	LUMP_SHADERS		1
52 #define	LUMP_PLANES			2
53 #define	LUMP_NODES			3
54 #define	LUMP_LEAFS			4
55 #define	LUMP_LEAFSURFACES	5
56 #define	LUMP_LEAFBRUSHES	6
57 #define	LUMP_MODELS			7
58 #define	LUMP_BRUSHES		8
59 #define	LUMP_BRUSHSIDES		9
60 #define	LUMP_DRAWVERTS		10
61 #define	LUMP_DRAWINDEXES	11
62 #define	LUMP_FOGS			12
63 #define	LUMP_SURFACES		13
64 #define	LUMP_LIGHTMAPS		14
65 #define	LUMP_LIGHTGRID		15
66 #define	LUMP_VISIBILITY		16
67 #define	HEADER_LUMPS		17
68 
69 
70 /* types */
71 typedef struct
72 {
73 	char		ident[ 4 ];
74 	int			version;
75 
76 	bspLump_t	lumps[ HEADER_LUMPS ];
77 }
78 ibspHeader_t;
79 
80 
81 
82 /* brush sides */
83 typedef struct
84 {
85 	int			planeNum;
86 	int			shaderNum;
87 }
88 ibspBrushSide_t;
89 
90 
CopyBrushSidesLump(ibspHeader_t * header)91 static void CopyBrushSidesLump( ibspHeader_t *header )
92 {
93 	int				i;
94 	ibspBrushSide_t	*in;
95 	bspBrushSide_t	*out;
96 
97 
98 	/* get count */
99 	numBSPBrushSides = GetLumpElements( (bspHeader_t*) header, LUMP_BRUSHSIDES, sizeof( *in ) );
100 
101 	/* copy */
102 	in = GetLump( (bspHeader_t*) header, LUMP_BRUSHSIDES );
103 	out = bspBrushSides;
104 	for( i = 0; i < numBSPBrushSides; i++ )
105 	{
106 		out->planeNum = in->planeNum;
107 		out->shaderNum = in->shaderNum;
108 		out->surfaceNum = -1;
109 		in++;
110 		out++;
111 	}
112 }
113 
114 
AddBrushSidesLump(FILE * file,ibspHeader_t * header)115 static void AddBrushSidesLump( FILE *file, ibspHeader_t *header )
116 {
117 	int				i, size;
118 	bspBrushSide_t	*in;
119 	ibspBrushSide_t	*buffer, *out;
120 
121 
122 	/* allocate output buffer */
123 	size = numBSPBrushSides * sizeof( *buffer );
124 	buffer = safe_malloc( size );
125 	memset( buffer, 0, size );
126 
127 	/* convert */
128 	in = bspBrushSides;
129 	out = buffer;
130 	for( i = 0; i < numBSPBrushSides; i++ )
131 	{
132 		out->planeNum = in->planeNum;
133 		out->shaderNum = in->shaderNum;
134 		in++;
135 		out++;
136 	}
137 
138 	/* write lump */
139 	AddLump( file, (bspHeader_t*) header, LUMP_BRUSHSIDES, buffer, size );
140 
141 	/* free buffer */
142 	free( buffer );
143 }
144 
145 
146 
147 /* drawsurfaces */
148 typedef struct ibspDrawSurface_s
149 {
150 	int			shaderNum;
151 	int			fogNum;
152 	int			surfaceType;
153 
154 	int			firstVert;
155 	int			numVerts;
156 
157 	int			firstIndex;
158 	int			numIndexes;
159 
160 	int			lightmapNum;
161 	int			lightmapX, lightmapY;
162 	int			lightmapWidth, lightmapHeight;
163 
164 	vec3_t		lightmapOrigin;
165 	vec3_t		lightmapVecs[ 3 ];
166 
167 	int			patchWidth;
168 	int			patchHeight;
169 }
170 ibspDrawSurface_t;
171 
172 
CopyDrawSurfacesLump(ibspHeader_t * header)173 static void CopyDrawSurfacesLump( ibspHeader_t *header )
174 {
175 	int					i, j;
176 	ibspDrawSurface_t	*in;
177 	bspDrawSurface_t	*out;
178 
179 
180 	/* get count */
181 	numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( *in ) );
182 	SetDrawSurfaces( numBSPDrawSurfaces );
183 
184 	/* copy */
185 	in = GetLump( (bspHeader_t*) header, LUMP_SURFACES );
186 	out = bspDrawSurfaces;
187 	for( i = 0; i < numBSPDrawSurfaces; i++ )
188 	{
189 		out->shaderNum = in->shaderNum;
190 		out->fogNum = in->fogNum;
191 		out->surfaceType = in->surfaceType;
192 		out->firstVert = in->firstVert;
193 		out->numVerts = in->numVerts;
194 		out->firstIndex = in->firstIndex;
195 		out->numIndexes = in->numIndexes;
196 
197 		out->lightmapStyles[ 0 ] = LS_NORMAL;
198 		out->vertexStyles[ 0 ] = LS_NORMAL;
199 		out->lightmapNum[ 0 ] = in->lightmapNum;
200 		out->lightmapX[ 0 ] = in->lightmapX;
201 		out->lightmapY[ 0 ] = in->lightmapY;
202 
203 		for( j = 1; j < MAX_LIGHTMAPS; j++ )
204 		{
205 			out->lightmapStyles[ j ] = LS_NONE;
206 			out->vertexStyles[ j ] = LS_NONE;
207 			out->lightmapNum[ j ] = -3;
208 			out->lightmapX[ j ] = 0;
209 			out->lightmapY[ j ] = 0;
210 		}
211 
212 		out->lightmapWidth = in->lightmapWidth;
213 		out->lightmapHeight = in->lightmapHeight;
214 
215 		VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
216 		VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
217 		VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
218 		VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
219 
220 		out->patchWidth = in->patchWidth;
221 		out->patchHeight = in->patchHeight;
222 
223 		in++;
224 		out++;
225 	}
226 }
227 
228 
AddDrawSurfacesLump(FILE * file,ibspHeader_t * header)229 static void AddDrawSurfacesLump( FILE *file, ibspHeader_t *header )
230 {
231 	int					i, size;
232 	bspDrawSurface_t	*in;
233 	ibspDrawSurface_t	*buffer, *out;
234 
235 
236 	/* allocate output buffer */
237 	size = numBSPDrawSurfaces * sizeof( *buffer );
238 	buffer = safe_malloc( size );
239 	memset( buffer, 0, size );
240 
241 	/* convert */
242 	in = bspDrawSurfaces;
243 	out = buffer;
244 	for( i = 0; i < numBSPDrawSurfaces; i++ )
245 	{
246 		out->shaderNum = in->shaderNum;
247 		out->fogNum = in->fogNum;
248 		out->surfaceType = in->surfaceType;
249 		out->firstVert = in->firstVert;
250 		out->numVerts = in->numVerts;
251 		out->firstIndex = in->firstIndex;
252 		out->numIndexes = in->numIndexes;
253 
254 		out->lightmapNum = in->lightmapNum[ 0 ];
255 		out->lightmapX = in->lightmapX[ 0 ];
256 		out->lightmapY = in->lightmapY[ 0 ];
257 		out->lightmapWidth = in->lightmapWidth;
258 		out->lightmapHeight = in->lightmapHeight;
259 
260 		VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
261 		VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
262 		VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
263 		VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
264 
265 		out->patchWidth = in->patchWidth;
266 		out->patchHeight = in->patchHeight;
267 
268 		in++;
269 		out++;
270 	}
271 
272 	/* write lump */
273 	AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, buffer, size );
274 
275 	/* free buffer */
276 	free( buffer );
277 }
278 
279 
280 
281 /* drawverts */
282 typedef struct
283 {
284 	vec3_t		xyz;
285 	float		st[ 2 ];
286 	float		lightmap[ 2 ];
287 	vec3_t		normal;
288 	byte		color[ 4 ];
289 }
290 ibspDrawVert_t;
291 
292 
CopyDrawVertsLump(ibspHeader_t * header)293 static void CopyDrawVertsLump( ibspHeader_t *header )
294 {
295 	int				i;
296 	ibspDrawVert_t	*in;
297 	bspDrawVert_t	*out;
298 
299 
300 	/* get count */
301 	numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( *in ) );
302 	SetDrawVerts( numBSPDrawVerts );
303 
304 	/* copy */
305 	in = GetLump( (bspHeader_t*) header, LUMP_DRAWVERTS );
306 	out = bspDrawVerts;
307 	for( i = 0; i < numBSPDrawVerts; i++ )
308 	{
309 		VectorCopy( in->xyz, out->xyz );
310 		out->st[ 0 ] = in->st[ 0 ];
311 		out->st[ 1 ] = in->st[ 1 ];
312 
313 		out->lightmap[ 0 ][ 0 ] = in->lightmap[ 0 ];
314 		out->lightmap[ 0 ][ 1 ] = in->lightmap[ 1 ];
315 
316 		VectorCopy( in->normal, out->normal );
317 
318 		out->color[ 0 ][ 0 ] = in->color[ 0 ];
319 		out->color[ 0 ][ 1 ] = in->color[ 1 ];
320 		out->color[ 0 ][ 2 ] = in->color[ 2 ];
321 		out->color[ 0 ][ 3 ] = in->color[ 3 ];
322 
323 		in++;
324 		out++;
325 	}
326 }
327 
328 
AddDrawVertsLump(FILE * file,ibspHeader_t * header)329 static void AddDrawVertsLump( FILE *file, ibspHeader_t *header )
330 {
331 	int				i, size;
332 	bspDrawVert_t	*in;
333 	ibspDrawVert_t	*buffer, *out;
334 
335 
336 	/* allocate output buffer */
337 	size = numBSPDrawVerts * sizeof( *buffer );
338 	buffer = safe_malloc( size );
339 	memset( buffer, 0, size );
340 
341 	/* convert */
342 	in = bspDrawVerts;
343 	out = buffer;
344 	for( i = 0; i < numBSPDrawVerts; i++ )
345 	{
346 		VectorCopy( in->xyz, out->xyz );
347 		out->st[ 0 ] = in->st[ 0 ];
348 		out->st[ 1 ] = in->st[ 1 ];
349 
350 		out->lightmap[ 0 ] = in->lightmap[ 0 ][ 0 ];
351 		out->lightmap[ 1 ] = in->lightmap[ 0 ][ 1 ];
352 
353 		VectorCopy( in->normal, out->normal );
354 
355 		out->color[ 0 ] = in->color[ 0 ][ 0 ];
356 		out->color[ 1 ] = in->color[ 0 ][ 1 ];
357 		out->color[ 2 ] = in->color[ 0 ][ 2 ];
358 		out->color[ 3 ] = in->color[ 0 ][ 3 ];
359 
360 		in++;
361 		out++;
362 	}
363 
364 	/* write lump */
365 	AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, buffer, size );
366 
367 	/* free buffer */
368 	free( buffer );
369 }
370 
371 
372 
373 /* light grid */
374 typedef struct
375 {
376 	byte		ambient[ 3 ];
377 	byte		directed[ 3 ];
378 	byte		latLong[ 2 ];
379 }
380 ibspGridPoint_t;
381 
382 
CopyLightGridLumps(ibspHeader_t * header)383 static void CopyLightGridLumps( ibspHeader_t *header )
384 {
385 	int				i, j;
386 	ibspGridPoint_t	*in;
387 	bspGridPoint_t	*out;
388 
389 
390 	/* get count */
391 	numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTGRID, sizeof( *in ) );
392 
393 	/* allocate buffer */
394 	bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
395 	memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
396 
397 	/* copy */
398 	in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
399 	out = bspGridPoints;
400 	for( i = 0; i < numBSPGridPoints; i++ )
401 	{
402 		for( j = 0; j < MAX_LIGHTMAPS; j++ )
403 		{
404 			VectorCopy( in->ambient, out->ambient[ j ] );
405 			VectorCopy( in->directed, out->directed[ j ] );
406 			out->styles[ j ] = LS_NONE;
407 		}
408 
409 		out->styles[ 0 ] = LS_NORMAL;
410 
411 		out->latLong[ 0 ] = in->latLong[ 0 ];
412 		out->latLong[ 1 ] = in->latLong[ 1 ];
413 
414 		in++;
415 		out++;
416 	}
417 }
418 
419 
AddLightGridLumps(FILE * file,ibspHeader_t * header)420 static void AddLightGridLumps( FILE *file, ibspHeader_t *header )
421 {
422 	int				i;
423 	bspGridPoint_t	*in;
424 	ibspGridPoint_t	*buffer, *out;
425 
426 
427 	/* dummy check */
428 	if( bspGridPoints == NULL )
429 		return;
430 
431 	/* allocate temporary buffer */
432 	buffer = safe_malloc( numBSPGridPoints * sizeof( *out ) );
433 
434 	/* convert */
435 	in = bspGridPoints;
436 	out = buffer;
437 	for( i = 0; i < numBSPGridPoints; i++ )
438 	{
439 		VectorCopy( in->ambient[ 0 ], out->ambient );
440 		VectorCopy( in->directed[ 0 ], out->directed );
441 
442 		out->latLong[ 0 ] = in->latLong[ 0 ];
443 		out->latLong[ 1 ] = in->latLong[ 1 ];
444 
445 		in++;
446 		out++;
447 	}
448 
449 	/* write lumps */
450 	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, buffer, (numBSPGridPoints * sizeof( *out )) );
451 
452 	/* free buffer (ydnar 2002-10-22: [bug 641] thanks Rap70r! */
453 	free( buffer );
454 }
455 
456 
457 
458 /*
459 LoadIBSPFile()
460 loads a quake 3 bsp file into memory
461 */
462 
LoadIBSPFile(const char * filename)463 void LoadIBSPFile( const char *filename )
464 {
465 	ibspHeader_t	*header;
466 
467 
468 	/* load the file header */
469 	LoadFile( filename, (void**) &header );
470 
471 	/* swap the header (except the first 4 bytes) */
472 	SwapBlock( (int*) ((byte*) header + sizeof( int )), sizeof( *header ) - sizeof( int ) );
473 
474 	/* make sure it matches the format we're trying to load */
475 	if( force == qfalse && *((int*) header->ident) != *((int*) game->bspIdent) )
476 		Error( "%s is not a %s file", filename, game->bspIdent );
477 	if( force == qfalse && header->version != game->bspVersion )
478 		Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
479 
480 	/* load/convert lumps */
481 	numBSPShaders = CopyLump( (bspHeader_t*) header, LUMP_SHADERS, bspShaders, sizeof( bspShader_t ) );
482 
483 	numBSPModels = CopyLump( (bspHeader_t*) header, LUMP_MODELS, bspModels, sizeof( bspModel_t ) );
484 
485 	numBSPPlanes = CopyLump( (bspHeader_t*) header, LUMP_PLANES, bspPlanes, sizeof( bspPlane_t ) );
486 
487 	numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) );
488 
489 	numBSPNodes = CopyLump( (bspHeader_t*) header, LUMP_NODES, bspNodes, sizeof( bspNode_t ) );
490 
491 	numBSPLeafSurfaces = CopyLump( (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ) );
492 
493 	numBSPLeafBrushes = CopyLump( (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ) );
494 
495 	numBSPBrushes = CopyLump( (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, sizeof( bspBrush_t ) );
496 
497 	CopyBrushSidesLump( header );
498 
499 	CopyDrawVertsLump( header );
500 
501 	CopyDrawSurfacesLump( header );
502 
503 	numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFog_t ) );
504 
505 	numBSPDrawIndexes = CopyLump( (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ) );
506 
507 	numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 );
508 
509 	numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 );
510 		bspLightBytes = safe_malloc( numBSPLightBytes );
511 		CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
512 
513 	bspEntDataSize = CopyLump( (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, 1);
514 
515 	CopyLightGridLumps( header );
516 
517 	/* free the file buffer */
518 	free( header );
519 }
520 
521 
522 
523 /*
524 WriteIBSPFile()
525 writes an id bsp file
526 */
527 
WriteIBSPFile(const char * filename)528 void WriteIBSPFile( const char *filename )
529 {
530 	ibspHeader_t	outheader, *header;
531 	FILE			*file;
532 	time_t			t;
533 	char			marker[ 1024 ];
534 	int				size;
535 
536 
537 	/* set header */
538 	header = &outheader;
539 	memset( header, 0, sizeof( *header ) );
540 
541 	//%	Swapfile();
542 
543 	/* set up header */
544 	*((int*) (bspHeader_t*) header->ident) = *((int*) game->bspIdent);
545 	header->version = LittleLong( game->bspVersion );
546 
547 	/* write initial header */
548 	file = SafeOpenWrite( filename );
549 	SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) );	/* overwritten later */
550 
551 	/* add marker lump */
552 	time( &t );
553 	sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
554 	AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
555 
556 	/* add lumps */
557 	AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
558 	AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
559 	AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
560 	AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
561 	AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes*sizeof( bspBrush_t ) );
562 	AddBrushSidesLump( file, header );
563 	AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
564 	AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
565 	AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
566 	AddDrawVertsLump( file, header );
567 	AddDrawSurfacesLump( file, header );
568 	AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
569 	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
570 	AddLightGridLumps( file, header );
571 	AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
572 	AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
573 	AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
574 
575 	/* emit bsp size */
576 	size = ftell( file );
577 	Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / (1024 * 1024), size );
578 
579 	/* write the completed header */
580 	fseek( file, 0, SEEK_SET );
581 	SafeWrite( file, header, sizeof( *header ) );
582 
583 	/* close the file */
584 	fclose( file );
585 }
586