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 ------------------------------------------------------------------------------- */
31 #define BSPFILE_ABSTRACT_C
41 /* -------------------------------------------------------------------------------
43 this file was copied out of the common directory in order to not break
44 compatibility with the q3map 1.x tree. it was moved out in order to support
45 the raven bsp format (RBSP) used in soldier of fortune 2 and jedi knight 2.
47 since each game has its own set of particular features, the data structures
48 below no longer directly correspond to the binary format of a particular game.
50 the translation will be done at bsp load/save time to keep any sort of
51 special-case code messiness out of the rest of the program.
53 ------------------------------------------------------------------------------- */
57 /* FIXME: remove the functions below that handle memory management of bsp file chunks */
59 int numBSPDrawVertsBuffer = 0;
66 numBSPDrawVertsBuffer = MAX_MAP_DRAW_VERTS / 37;
68 bspDrawVerts = safe_malloc_info(sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer, "IncDrawVerts");
71 else if(numBSPDrawVerts > numBSPDrawVertsBuffer)
73 numBSPDrawVertsBuffer *= 3; // multiply by 1.5
74 numBSPDrawVertsBuffer /= 2;
76 if(numBSPDrawVertsBuffer > MAX_MAP_DRAW_VERTS)
77 numBSPDrawVertsBuffer = MAX_MAP_DRAW_VERTS;
79 bspDrawVerts = realloc(bspDrawVerts, sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer);
82 Error( "realloc() failed (IncDrawVerts)");
85 memset(bspDrawVerts + (numBSPDrawVerts - 1), 0, sizeof(bspDrawVert_t));
88 void SetDrawVerts(int n)
94 numBSPDrawVertsBuffer = numBSPDrawVerts;
96 bspDrawVerts = safe_malloc_info(sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer, "IncDrawVerts");
98 memset(bspDrawVerts, 0, n * sizeof(bspDrawVert_t));
101 int numBSPDrawSurfacesBuffer = 0;
102 void SetDrawSurfacesBuffer()
104 if(bspDrawSurfaces != 0)
105 free(bspDrawSurfaces);
107 numBSPDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
109 bspDrawSurfaces = safe_malloc_info(sizeof(bspDrawSurface_t) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces");
111 memset(bspDrawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof(bspDrawVert_t));
114 void SetDrawSurfaces(int n)
116 if(bspDrawSurfaces != 0)
117 free(bspDrawSurfaces);
119 numBSPDrawSurfaces = n;
120 numBSPDrawSurfacesBuffer = numBSPDrawSurfaces;
122 bspDrawSurfaces = safe_malloc_info(sizeof(bspDrawSurface_t) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces");
124 memset(bspDrawSurfaces, 0, n * sizeof(bspDrawVert_t));
127 void BSPFilesCleanup()
129 if(bspDrawVerts != 0)
131 if(bspDrawSurfaces != 0)
132 free(bspDrawSurfaces);
133 if(bspLightBytes != 0)
135 if(bspGridPoints != 0)
146 if all values are 32 bits, this can be used to swap everything
149 void SwapBlock( int *block, int size )
160 for( i = 0; i < size; i++ )
161 block[ i ] = LittleLong( block[ i ] );
168 byte swaps all data in the abstract bsp
171 void SwapBSPFile( void )
177 SwapBlock( (int*) bspModels, numBSPModels * sizeof( bspModels[ 0 ] ) );
179 /* shaders (don't swap the name) */
180 for( i = 0; i < numBSPShaders ; i++ )
182 bspShaders[ i ].contentFlags = LittleLong( bspShaders[ i ].contentFlags );
183 bspShaders[ i ].surfaceFlags = LittleLong( bspShaders[ i ].surfaceFlags );
187 SwapBlock( (int*) bspPlanes, numBSPPlanes * sizeof( bspPlanes[ 0 ] ) );
190 SwapBlock( (int*) bspNodes, numBSPNodes * sizeof( bspNodes[ 0 ] ) );
193 SwapBlock( (int*) bspLeafs, numBSPLeafs * sizeof( bspLeafs[ 0 ] ) );
196 SwapBlock( (int*) bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
199 SwapBlock( (int*) bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
202 SwapBlock( (int*) bspBrushes, numBSPBrushes * sizeof( bspBrushes[ 0 ] ) );
205 SwapBlock( (int*) bspBrushSides, numBSPBrushSides * sizeof( bspBrushSides[ 0 ] ) );
208 ((int*) &bspVisBytes)[ 0 ] = LittleLong( ((int*) &bspVisBytes)[ 0 ] );
209 ((int*) &bspVisBytes)[ 1 ] = LittleLong( ((int*) &bspVisBytes)[ 1 ] );
211 /* drawverts (don't swap colors) */
212 for( i = 0; i < numBSPDrawVerts; i++ )
214 bspDrawVerts[ i ].xyz[ 0 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 0 ] );
215 bspDrawVerts[ i ].xyz[ 1 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 1 ] );
216 bspDrawVerts[ i ].xyz[ 2 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 2 ] );
217 bspDrawVerts[ i ].normal[ 0 ] = LittleFloat( bspDrawVerts[ i ].normal[ 0 ] );
218 bspDrawVerts[ i ].normal[ 1 ] = LittleFloat( bspDrawVerts[ i ].normal[ 1 ] );
219 bspDrawVerts[ i ].normal[ 2 ] = LittleFloat( bspDrawVerts[ i ].normal[ 2 ] );
220 bspDrawVerts[ i ].st[ 0 ] = LittleFloat( bspDrawVerts[ i ].st[ 0 ] );
221 bspDrawVerts[ i ].st[ 1 ] = LittleFloat( bspDrawVerts[ i ].st[ 1 ] );
222 for( j = 0; j < MAX_LIGHTMAPS; j++ )
224 bspDrawVerts[ i ].lightmap[ j ][ 0 ] = LittleFloat( bspDrawVerts[ i ].lightmap[ j ][ 0 ] );
225 bspDrawVerts[ i ].lightmap[ j ][ 1 ] = LittleFloat( bspDrawVerts[ i ].lightmap[ j ][ 1 ] );
230 SwapBlock( (int*) bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[0] ) );
233 /* note: rbsp files (and hence q3map2 abstract bsp) have byte lightstyles index arrays, this follows sof2map convention */
234 SwapBlock( (int*) bspDrawSurfaces, numBSPDrawSurfaces * sizeof( bspDrawSurfaces[ 0 ] ) );
237 for( i = 0; i < numBSPFogs; i++ )
239 bspFogs[ i ].brushNum = LittleLong( bspFogs[ i ].brushNum );
240 bspFogs[ i ].visibleSide = LittleLong( bspFogs[ i ].visibleSide );
244 for( i = 0; i < numBSPAds; i++ )
246 bspAds[ i ].cellId = LittleLong( bspAds[ i ].cellId );
247 bspAds[ i ].normal[ 0 ] = LittleFloat( bspAds[ i ].normal[ 0 ] );
248 bspAds[ i ].normal[ 1 ] = LittleFloat( bspAds[ i ].normal[ 1 ] );
249 bspAds[ i ].normal[ 2 ] = LittleFloat( bspAds[ i ].normal[ 2 ] );
251 for( j = 0; j < 4; j++ )
253 bspAds[ i ].rect[j][ 0 ] = LittleFloat( bspAds[ i ].rect[j][ 0 ] );
254 bspAds[ i ].rect[j][ 1 ] = LittleFloat( bspAds[ i ].rect[j][ 1 ] );
255 bspAds[ i ].rect[j][ 2 ] = LittleFloat( bspAds[ i ].rect[j][ 2 ] );
258 //bspAds[ i ].model[ MAX_QPATH ];
266 gets the number of elements in a bsp lump
269 int GetLumpElements( bspHeader_t *header, int lump, int size )
271 /* check for odd size */
272 if( header->lumps[ lump ].length % size )
276 Sys_Printf( "WARNING: GetLumpElements: odd lump size (%d) in lump %d\n", header->lumps[ lump ].length, lump );
280 Error( "GetLumpElements: odd lump size (%d) in lump %d", header->lumps[ lump ].length, lump );
283 /* return element count */
284 return header->lumps[ lump ].length / size;
291 returns a pointer to the specified lump
294 void *GetLump( bspHeader_t *header, int lump )
296 return (void*)( (byte*) header + header->lumps[ lump ].offset);
303 copies a bsp file lump into a destination buffer
306 int CopyLump( bspHeader_t *header, int lump, void *dest, int size )
311 /* get lump length and offset */
312 length = header->lumps[ lump ].length;
313 offset = header->lumps[ lump ].offset;
315 /* handle erroneous cases */
322 Sys_Printf( "WARNING: CopyLump: odd lump size (%d) in lump %d\n", length, lump );
326 Error( "CopyLump: odd lump size (%d) in lump %d", length, lump );
329 /* copy block of memory and return */
330 memcpy( dest, (byte*) header + offset, length );
331 return length / size;
338 adds a lump to an outgoing bsp file
341 void AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length )
346 /* add lump to bsp file header */
347 lump = &header->lumps[ lumpNum ];
348 lump->offset = LittleLong( ftell( file ) );
349 lump->length = LittleLong( length );
351 /* write lump to file */
352 SafeWrite( file, data, (length + 3) & ~3 );
359 loads a bsp file into memory
362 void LoadBSPFile( const char *filename )
365 if( game == NULL || game->load == NULL )
366 Error( "LoadBSPFile: unsupported BSP file format" );
368 /* load it, then byte swap the in-memory version */
369 game->load( filename );
380 void WriteBSPFile( const char *filename )
382 char tempname[ 1024 ];
387 if( game == NULL || game->write == NULL )
388 Error( "WriteBSPFile: unsupported BSP file format" );
390 /* make fake temp name so existing bsp file isn't damaged in case write process fails */
392 sprintf( tempname, "%s.%08X", filename, (int) tm );
394 /* byteswap, write the bsp, then swap back so it can be manipulated further */
396 game->write( tempname );
399 /* replace existing bsp file */
401 rename( tempname, filename );
408 dumps info about current file
411 void PrintBSPFileSizes( void )
413 /* parse entities first */
414 if( numEntities <= 0 )
417 /* note that this is abstracted */
418 Sys_Printf( "Abstracted BSP file components (*actual sizes may differ)\n" );
420 /* print various and sundry bits */
421 Sys_Printf( "%9d models %9d\n",
422 numBSPModels, (int) (numBSPModels * sizeof( bspModel_t )) );
423 Sys_Printf( "%9d shaders %9d\n",
424 numBSPShaders, (int) (numBSPShaders * sizeof( bspShader_t )) );
425 Sys_Printf( "%9d brushes %9d\n",
426 numBSPBrushes, (int) (numBSPBrushes * sizeof( bspBrush_t )) );
427 Sys_Printf( "%9d brushsides %9d *\n",
428 numBSPBrushSides, (int) (numBSPBrushSides * sizeof( bspBrushSide_t )) );
429 Sys_Printf( "%9d fogs %9d\n",
430 numBSPFogs, (int) (numBSPFogs * sizeof( bspFog_t ) ) );
431 Sys_Printf( "%9d planes %9d\n",
432 numBSPPlanes, (int) (numBSPPlanes * sizeof( bspPlane_t )) );
433 Sys_Printf( "%9d entdata %9d\n",
434 numEntities, bspEntDataSize );
437 Sys_Printf( "%9d nodes %9d\n",
438 numBSPNodes, (int) (numBSPNodes * sizeof( bspNode_t)) );
439 Sys_Printf( "%9d leafs %9d\n",
440 numBSPLeafs, (int) (numBSPLeafs * sizeof( bspLeaf_t )) );
441 Sys_Printf( "%9d leafsurfaces %9d\n",
442 numBSPLeafSurfaces, (int) (numBSPLeafSurfaces * sizeof( *bspLeafSurfaces )) );
443 Sys_Printf( "%9d leafbrushes %9d\n",
444 numBSPLeafBrushes, (int) (numBSPLeafBrushes * sizeof( *bspLeafBrushes )) );
447 Sys_Printf( "%9d drawsurfaces %9d *\n",
448 numBSPDrawSurfaces, (int) (numBSPDrawSurfaces * sizeof( *bspDrawSurfaces )) );
449 Sys_Printf( "%9d drawverts %9d *\n",
450 numBSPDrawVerts, (int) (numBSPDrawVerts * sizeof( *bspDrawVerts )) );
451 Sys_Printf( "%9d drawindexes %9d\n",
452 numBSPDrawIndexes, (int) (numBSPDrawIndexes * sizeof( *bspDrawIndexes )) );
455 Sys_Printf( "%9d lightmaps %9d\n",
456 numBSPLightBytes / (LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3), numBSPLightBytes );
457 Sys_Printf( "%9d lightgrid %9d *\n",
458 numBSPGridPoints, (int) (numBSPGridPoints * sizeof( *bspGridPoints )) );
459 Sys_Printf( " visibility %9d\n",
465 /* -------------------------------------------------------------------------------
469 ------------------------------------------------------------------------------- */
474 strips low byte chars off the end of a string
477 void StripTrailing( char *e )
482 s = e + strlen( e ) - 1;
483 while( s >= e && *s <= 32 )
494 parses a single quoted "key" "value" pair into an epair struct
497 epair_t *ParseEPair( void )
502 /* allocate and clear new epair */
503 e = safe_malloc( sizeof( epair_t ) );
504 memset( e, 0, sizeof( epair_t ) );
507 if( strlen( token ) >= (MAX_KEY - 1) )
508 Error( "ParseEPair: token too long" );
510 e->key = copystring( token );
514 if( strlen( token ) >= MAX_VALUE - 1 )
515 Error( "ParseEpar: token too long" );
516 e->value = copystring( token );
518 /* strip trailing spaces that sometimes get accidentally added in the editor */
519 StripTrailing( e->key );
520 StripTrailing( e->value );
530 parses an entity's epairs
533 qboolean ParseEntity( void )
539 if( !GetToken( qtrue ) )
541 if( strcmp( token, "{" ) )
542 Error( "ParseEntity: { not found" );
543 if( numEntities == MAX_MAP_ENTITIES )
544 Error( "numEntities == MAX_MAP_ENTITIES" );
546 /* create new entity */
547 mapEnt = &entities[ numEntities ];
553 if( !GetToken( qtrue ) )
554 Error( "ParseEntity: EOF without closing brace" );
555 if( !EPAIR_STRCMP( token, "}" ) )
558 e->next = mapEnt->epairs;
562 /* return to sender */
570 parses the bsp entity data string into entities
573 void ParseEntities( void )
576 ParseFromMemory( bspEntData, bspEntDataSize );
577 while( ParseEntity() );
579 /* ydnar: set number of bsp entities in case a map is loaded on top */
580 numBSPEntities = numEntities;
587 generates the dentdata string from all the entities.
588 this allows the utilities to add or remove key/value
589 pairs to the data created by the map editor
592 void UnparseEntities( void )
598 char key[ 1024 ], value[ 1024 ];
607 /* run through entity list */
608 for( i = 0; i < numBSPEntities && i < numEntities; i++ )
611 ep = entities[ i ].epairs;
613 continue; /* ent got removed */
615 /* ydnar: certain entities get stripped from bsp file */
616 value2 = ValueForKey( &entities[ i ], "classname" );
617 if( !Q_stricmp( value2, "misc_model" ) ||
618 !Q_stricmp( value2, "_decal" ) ||
619 !Q_stricmp( value2, "_skybox" ) )
622 /* add beginning brace */
623 strcat( end, "{\n" );
626 /* walk epair list */
627 for( ep = entities[ i ].epairs; ep != NULL; ep = ep->next )
630 strcpy( key, ep->key );
631 StripTrailing( key );
632 strcpy( value, ep->value );
633 StripTrailing( value );
636 sprintf( line, "\"%s\" \"%s\"\n", key, value );
638 end += strlen( line );
641 /* add trailing brace */
645 /* check for overflow */
646 if( end > buf + MAX_MAP_ENTSTRING )
647 Error( "Entity text too long" );
651 bspEntDataSize = end - buf + 1;
658 prints an entity's epairs to the console
661 void PrintEntity( const entity_t *ent )
666 Sys_Printf( "------- entity %p -------\n", ent );
667 for( ep = ent->epairs; ep != NULL; ep = ep->next )
668 Sys_Printf( "%s = %s\n", ep->key, ep->value );
676 sets an epair in an entity
679 void SetKeyValue( entity_t *ent, const char *key, const char *value )
684 /* check for existing epair */
685 for( ep = ent->epairs; ep != NULL; ep = ep->next )
687 if( !EPAIR_STRCMP( ep->key, key ) )
690 ep->value = copystring( value );
695 /* create new epair */
696 ep = safe_malloc( sizeof( *ep ) );
697 ep->next = ent->epairs;
699 ep->key = copystring( key );
700 ep->value = copystring( value );
707 gets the value for an entity key
710 const char *ValueForKey( const entity_t *ent, const char *key )
719 /* walk epair list */
720 for( ep = ent->epairs; ep != NULL; ep = ep->next )
722 if( !EPAIR_STRCMP( ep->key, key ) )
726 /* if no match, return empty string */
734 gets the integer point value for an entity key
737 int IntForKey( const entity_t *ent, const char *key )
742 k = ValueForKey( ent, key );
750 gets the floating point value for an entity key
753 vec_t FloatForKey( const entity_t *ent, const char *key )
758 k = ValueForKey( ent, key );
766 gets a 3-element vector value for an entity key
769 void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec )
776 k = ValueForKey( ent, key );
778 /* scanf into doubles, then assign, so it is vec_t size independent */
780 sscanf( k, "%lf %lf %lf", &v1, &v2, &v3 );
790 finds an entity target
793 entity_t *FindTargetEntity( const char *target )
799 /* walk entity list */
800 for( i = 0; i < numEntities; i++ )
802 n = ValueForKey( &entities[ i ], "targetname" );
803 if ( !strcmp( n, target ) )
804 return &entities[ i ];
814 GetEntityShadowFlags() - ydnar
815 gets an entity's shadow flags
816 note: does not set them to defaults if the keys are not found!
819 void GetEntityShadowFlags( const entity_t *ent, const entity_t *ent2, int *castShadows, int *recvShadows )
824 /* get cast shadows */
825 if( castShadows != NULL )
827 value = ValueForKey( ent, "_castShadows" );
828 if( value[ 0 ] == '\0' )
829 value = ValueForKey( ent, "_cs" );
830 if( value[ 0 ] == '\0' )
831 value = ValueForKey( ent2, "_castShadows" );
832 if( value[ 0 ] == '\0' )
833 value = ValueForKey( ent2, "_cs" );
834 if( value[ 0 ] != '\0' )
835 *castShadows = atoi( value );
839 if( recvShadows != NULL )
841 value = ValueForKey( ent, "_receiveShadows" );
842 if( value[ 0 ] == '\0' )
843 value = ValueForKey( ent, "_rs" );
844 if( value[ 0 ] == '\0' )
845 value = ValueForKey( ent2, "_receiveShadows" );
846 if( value[ 0 ] == '\0' )
847 value = ValueForKey( ent2, "_rs" );
848 if( value[ 0 ] != '\0' )
849 *recvShadows = atoi( value );