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 ------------------------------------------------------------------------------- */
32 #define BSPFILE_ABSTRACT_C
42 /* -------------------------------------------------------------------------------
44 this file was copied out of the common directory in order to not break
45 compatibility with the q3map 1.x tree. it was moved out in order to support
46 the raven bsp format (RBSP) used in soldier of fortune 2 and jedi knight 2.
48 since each game has its own set of particular features, the data structures
49 below no longer directly correspond to the binary format of a particular game.
51 the translation will be done at bsp load/save time to keep any sort of
52 special-case code messiness out of the rest of the program.
54 ------------------------------------------------------------------------------- */
58 /* FIXME: remove the functions below that handle memory management of bsp file chunks */
60 int numBSPDrawVertsBuffer = 0;
67 numBSPDrawVertsBuffer = MAX_MAP_DRAW_VERTS / 37;
69 bspDrawVerts = safe_malloc_info(sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer, "IncDrawVerts");
72 else if(numBSPDrawVerts > numBSPDrawVertsBuffer)
74 numBSPDrawVertsBuffer *= 3; // multiply by 1.5
75 numBSPDrawVertsBuffer /= 2;
77 if(numBSPDrawVertsBuffer > MAX_MAP_DRAW_VERTS)
78 numBSPDrawVertsBuffer = MAX_MAP_DRAW_VERTS;
80 bspDrawVerts = realloc(bspDrawVerts, sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer);
83 Error( "realloc() failed (IncDrawVerts)");
86 memset(bspDrawVerts + (numBSPDrawVerts - 1), 0, sizeof(bspDrawVert_t));
89 void SetDrawVerts(int n)
95 numBSPDrawVertsBuffer = numBSPDrawVerts;
97 bspDrawVerts = safe_malloc_info(sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer, "IncDrawVerts");
99 memset(bspDrawVerts, 0, n * sizeof(bspDrawVert_t));
102 int numBSPDrawSurfacesBuffer = 0;
103 void SetDrawSurfacesBuffer()
105 if(bspDrawSurfaces != 0)
106 free(bspDrawSurfaces);
108 numBSPDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
110 bspDrawSurfaces = safe_malloc_info(sizeof(bspDrawSurface_t) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces");
112 memset(bspDrawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof(bspDrawVert_t));
115 void SetDrawSurfaces(int n)
117 if(bspDrawSurfaces != 0)
118 free(bspDrawSurfaces);
120 numBSPDrawSurfaces = n;
121 numBSPDrawSurfacesBuffer = numBSPDrawSurfaces;
123 bspDrawSurfaces = safe_malloc_info(sizeof(bspDrawSurface_t) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces");
125 memset(bspDrawSurfaces, 0, n * sizeof(bspDrawVert_t));
128 void BSPFilesCleanup()
130 if(bspDrawVerts != 0)
132 if(bspDrawSurfaces != 0)
133 free(bspDrawSurfaces);
134 if(bspLightBytes != 0)
136 if(bspGridPoints != 0)
147 if all values are 32 bits, this can be used to swap everything
150 void SwapBlock( int *block, int size )
161 for( i = 0; i < size; i++ )
162 block[ i ] = LittleLong( block[ i ] );
169 byte swaps all data in the abstract bsp
172 void SwapBSPFile( void )
178 SwapBlock( (int*) bspModels, numBSPModels * sizeof( bspModels[ 0 ] ) );
180 /* shaders (don't swap the name) */
181 for( i = 0; i < numBSPShaders ; i++ )
183 bspShaders[ i ].contentFlags = LittleLong( bspShaders[ i ].contentFlags );
184 bspShaders[ i ].surfaceFlags = LittleLong( bspShaders[ i ].surfaceFlags );
188 SwapBlock( (int*) bspPlanes, numBSPPlanes * sizeof( bspPlanes[ 0 ] ) );
191 SwapBlock( (int*) bspNodes, numBSPNodes * sizeof( bspNodes[ 0 ] ) );
194 SwapBlock( (int*) bspLeafs, numBSPLeafs * sizeof( bspLeafs[ 0 ] ) );
197 SwapBlock( (int*) bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
200 SwapBlock( (int*) bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
203 SwapBlock( (int*) bspBrushes, numBSPBrushes * sizeof( bspBrushes[ 0 ] ) );
206 SwapBlock( (int*) bspBrushSides, numBSPBrushSides * sizeof( bspBrushSides[ 0 ] ) );
209 ((int*) &bspVisBytes)[ 0 ] = LittleLong( ((int*) &bspVisBytes)[ 0 ] );
210 ((int*) &bspVisBytes)[ 1 ] = LittleLong( ((int*) &bspVisBytes)[ 1 ] );
212 /* drawverts (don't swap colors) */
213 for( i = 0; i < numBSPDrawVerts; i++ )
215 bspDrawVerts[ i ].xyz[ 0 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 0 ] );
216 bspDrawVerts[ i ].xyz[ 1 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 1 ] );
217 bspDrawVerts[ i ].xyz[ 2 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 2 ] );
218 bspDrawVerts[ i ].normal[ 0 ] = LittleFloat( bspDrawVerts[ i ].normal[ 0 ] );
219 bspDrawVerts[ i ].normal[ 1 ] = LittleFloat( bspDrawVerts[ i ].normal[ 1 ] );
220 bspDrawVerts[ i ].normal[ 2 ] = LittleFloat( bspDrawVerts[ i ].normal[ 2 ] );
221 bspDrawVerts[ i ].st[ 0 ] = LittleFloat( bspDrawVerts[ i ].st[ 0 ] );
222 bspDrawVerts[ i ].st[ 1 ] = LittleFloat( bspDrawVerts[ i ].st[ 1 ] );
223 for( j = 0; j < MAX_LIGHTMAPS; j++ )
225 bspDrawVerts[ i ].lightmap[ j ][ 0 ] = LittleFloat( bspDrawVerts[ i ].lightmap[ j ][ 0 ] );
226 bspDrawVerts[ i ].lightmap[ j ][ 1 ] = LittleFloat( bspDrawVerts[ i ].lightmap[ j ][ 1 ] );
231 SwapBlock( (int*) bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[0] ) );
234 /* note: rbsp files (and hence q3map2 abstract bsp) have byte lightstyles index arrays, this follows sof2map convention */
235 SwapBlock( (int*) bspDrawSurfaces, numBSPDrawSurfaces * sizeof( bspDrawSurfaces[ 0 ] ) );
238 for( i = 0; i < numBSPFogs; i++ )
240 bspFogs[ i ].brushNum = LittleLong( bspFogs[ i ].brushNum );
241 bspFogs[ i ].visibleSide = LittleLong( bspFogs[ i ].visibleSide );
245 for( i = 0; i < numBSPAds; i++ )
247 bspAds[ i ].cellId = LittleLong( bspAds[ i ].cellId );
248 bspAds[ i ].normal[ 0 ] = LittleFloat( bspAds[ i ].normal[ 0 ] );
249 bspAds[ i ].normal[ 1 ] = LittleFloat( bspAds[ i ].normal[ 1 ] );
250 bspAds[ i ].normal[ 2 ] = LittleFloat( bspAds[ i ].normal[ 2 ] );
252 for( j = 0; j < 4; j++ )
254 bspAds[ i ].rect[j][ 0 ] = LittleFloat( bspAds[ i ].rect[j][ 0 ] );
255 bspAds[ i ].rect[j][ 1 ] = LittleFloat( bspAds[ i ].rect[j][ 1 ] );
256 bspAds[ i ].rect[j][ 2 ] = LittleFloat( bspAds[ i ].rect[j][ 2 ] );
259 //bspAds[ i ].model[ MAX_QPATH ];
267 gets the number of elements in a bsp lump
270 int GetLumpElements( bspHeader_t *header, int lump, int size )
272 /* check for odd size */
273 if( header->lumps[ lump ].length % size )
277 Sys_Printf( "WARNING: GetLumpElements: odd lump size (%d) in lump %d\n", header->lumps[ lump ].length, lump );
281 Error( "GetLumpElements: odd lump size (%d) in lump %d", header->lumps[ lump ].length, lump );
284 /* return element count */
285 return header->lumps[ lump ].length / size;
292 returns a pointer to the specified lump
295 void *GetLump( bspHeader_t *header, int lump )
297 return (void*)( (byte*) header + header->lumps[ lump ].offset);
304 copies a bsp file lump into a destination buffer
307 int CopyLump( bspHeader_t *header, int lump, void *dest, int size )
312 /* get lump length and offset */
313 length = header->lumps[ lump ].length;
314 offset = header->lumps[ lump ].offset;
316 /* handle erroneous cases */
323 Sys_Printf( "WARNING: CopyLump: odd lump size (%d) in lump %d\n", length, lump );
327 Error( "CopyLump: odd lump size (%d) in lump %d", length, lump );
330 /* copy block of memory and return */
331 memcpy( dest, (byte*) header + offset, length );
332 return length / size;
339 adds a lump to an outgoing bsp file
342 void AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length )
347 /* add lump to bsp file header */
348 lump = &header->lumps[ lumpNum ];
349 lump->offset = LittleLong( ftell( file ) );
350 lump->length = LittleLong( length );
352 /* write lump to file */
353 SafeWrite( file, data, (length + 3) & ~3 );
360 loads a bsp file into memory
363 void LoadBSPFile( const char *filename )
366 if( game == NULL || game->load == NULL )
367 Error( "LoadBSPFile: unsupported BSP file format" );
369 /* load it, then byte swap the in-memory version */
370 game->load( filename );
381 void WriteBSPFile( const char *filename )
383 char tempname[ 1024 ];
388 if( game == NULL || game->write == NULL )
389 Error( "WriteBSPFile: unsupported BSP file format" );
391 /* make fake temp name so existing bsp file isn't damaged in case write process fails */
393 sprintf( tempname, "%s.%08X", filename, (int) tm );
395 /* byteswap, write the bsp, then swap back so it can be manipulated further */
397 game->write( tempname );
400 /* replace existing bsp file */
402 rename( tempname, filename );
409 dumps info about current file
412 void PrintBSPFileSizes( void )
414 /* parse entities first */
415 if( numEntities <= 0 )
418 /* note that this is abstracted */
419 Sys_Printf( "Abstracted BSP file components (*actual sizes may differ)\n" );
421 /* print various and sundry bits */
422 Sys_Printf( "%9d models %9d\n",
423 numBSPModels, (int) (numBSPModels * sizeof( bspModel_t )) );
424 Sys_Printf( "%9d shaders %9d\n",
425 numBSPShaders, (int) (numBSPShaders * sizeof( bspShader_t )) );
426 Sys_Printf( "%9d brushes %9d\n",
427 numBSPBrushes, (int) (numBSPBrushes * sizeof( bspBrush_t )) );
428 Sys_Printf( "%9d brushsides %9d *\n",
429 numBSPBrushSides, (int) (numBSPBrushSides * sizeof( bspBrushSide_t )) );
430 Sys_Printf( "%9d fogs %9d\n",
431 numBSPFogs, (int) (numBSPFogs * sizeof( bspFog_t ) ) );
432 Sys_Printf( "%9d planes %9d\n",
433 numBSPPlanes, (int) (numBSPPlanes * sizeof( bspPlane_t )) );
434 Sys_Printf( "%9d entdata %9d\n",
435 numEntities, bspEntDataSize );
438 Sys_Printf( "%9d nodes %9d\n",
439 numBSPNodes, (int) (numBSPNodes * sizeof( bspNode_t)) );
440 Sys_Printf( "%9d leafs %9d\n",
441 numBSPLeafs, (int) (numBSPLeafs * sizeof( bspLeaf_t )) );
442 Sys_Printf( "%9d leafsurfaces %9d\n",
443 numBSPLeafSurfaces, (int) (numBSPLeafSurfaces * sizeof( *bspLeafSurfaces )) );
444 Sys_Printf( "%9d leafbrushes %9d\n",
445 numBSPLeafBrushes, (int) (numBSPLeafBrushes * sizeof( *bspLeafBrushes )) );
448 Sys_Printf( "%9d drawsurfaces %9d *\n",
449 numBSPDrawSurfaces, (int) (numBSPDrawSurfaces * sizeof( *bspDrawSurfaces )) );
450 Sys_Printf( "%9d drawverts %9d *\n",
451 numBSPDrawVerts, (int) (numBSPDrawVerts * sizeof( *bspDrawVerts )) );
452 Sys_Printf( "%9d drawindexes %9d\n",
453 numBSPDrawIndexes, (int) (numBSPDrawIndexes * sizeof( *bspDrawIndexes )) );
456 Sys_Printf( "%9d lightmaps %9d\n",
457 numBSPLightBytes / (game->lightmapSize * game->lightmapSize * 3), numBSPLightBytes );
458 Sys_Printf( "%9d lightgrid %9d *\n",
459 numBSPGridPoints, (int) (numBSPGridPoints * sizeof( *bspGridPoints )) );
460 Sys_Printf( " visibility %9d\n",
466 /* -------------------------------------------------------------------------------
470 ------------------------------------------------------------------------------- */
475 strips low byte chars off the end of a string
478 void StripTrailing( char *e )
483 s = e + strlen( e ) - 1;
484 while( s >= e && *s <= 32 )
495 parses a single quoted "key" "value" pair into an epair struct
498 epair_t *ParseEPair( void )
503 /* allocate and clear new epair */
504 e = safe_malloc( sizeof( epair_t ) );
505 memset( e, 0, sizeof( epair_t ) );
508 if( strlen( token ) >= (MAX_KEY - 1) )
509 Error( "ParseEPair: token too long" );
511 e->key = copystring( token );
515 if( strlen( token ) >= MAX_VALUE - 1 )
516 Error( "ParseEpar: token too long" );
517 e->value = copystring( token );
519 /* strip trailing spaces that sometimes get accidentally added in the editor */
520 StripTrailing( e->key );
521 StripTrailing( e->value );
531 parses an entity's epairs
534 qboolean ParseEntity( void )
540 if( !GetToken( qtrue ) )
542 if( strcmp( token, "{" ) )
543 Error( "ParseEntity: { not found" );
544 if( numEntities == MAX_MAP_ENTITIES )
545 Error( "numEntities == MAX_MAP_ENTITIES" );
547 /* create new entity */
548 mapEnt = &entities[ numEntities ];
554 if( !GetToken( qtrue ) )
555 Error( "ParseEntity: EOF without closing brace" );
556 if( !EPAIR_STRCMP( token, "}" ) )
559 e->next = mapEnt->epairs;
563 /* return to sender */
571 parses the bsp entity data string into entities
574 void ParseEntities( void )
577 ParseFromMemory( bspEntData, bspEntDataSize );
578 while( ParseEntity() );
580 /* ydnar: set number of bsp entities in case a map is loaded on top */
581 numBSPEntities = numEntities;
588 generates the dentdata string from all the entities.
589 this allows the utilities to add or remove key/value
590 pairs to the data created by the map editor
593 void UnparseEntities( void )
599 char key[ 1024 ], value[ 1024 ];
608 /* run through entity list */
609 for( i = 0; i < numBSPEntities && i < numEntities; i++ )
612 ep = entities[ i ].epairs;
614 continue; /* ent got removed */
616 /* ydnar: certain entities get stripped from bsp file */
617 value2 = ValueForKey( &entities[ i ], "classname" );
618 if( !Q_stricmp( value2, "misc_model" ) ||
619 !Q_stricmp( value2, "_decal" ) ||
620 !Q_stricmp( value2, "_skybox" ) )
623 /* add beginning brace */
624 strcat( end, "{\n" );
627 /* walk epair list */
628 for( ep = entities[ i ].epairs; ep != NULL; ep = ep->next )
631 strcpy( key, ep->key );
632 StripTrailing( key );
633 strcpy( value, ep->value );
634 StripTrailing( value );
637 sprintf( line, "\"%s\" \"%s\"\n", key, value );
639 end += strlen( line );
642 /* add trailing brace */
646 /* check for overflow */
647 if( end > buf + MAX_MAP_ENTSTRING )
648 Error( "Entity text too long" );
652 bspEntDataSize = end - buf + 1;
659 prints an entity's epairs to the console
662 void PrintEntity( const entity_t *ent )
667 Sys_Printf( "------- entity %p -------\n", ent );
668 for( ep = ent->epairs; ep != NULL; ep = ep->next )
669 Sys_Printf( "%s = %s\n", ep->key, ep->value );
677 sets an epair in an entity
680 void SetKeyValue( entity_t *ent, const char *key, const char *value )
685 /* check for existing epair */
686 for( ep = ent->epairs; ep != NULL; ep = ep->next )
688 if( !EPAIR_STRCMP( ep->key, key ) )
691 ep->value = copystring( value );
696 /* create new epair */
697 ep = safe_malloc( sizeof( *ep ) );
698 ep->next = ent->epairs;
700 ep->key = copystring( key );
701 ep->value = copystring( value );
708 gets the value for an entity key
711 const char *ValueForKey( const entity_t *ent, const char *key )
720 /* walk epair list */
721 for( ep = ent->epairs; ep != NULL; ep = ep->next )
723 if( !EPAIR_STRCMP( ep->key, key ) )
727 /* if no match, return empty string */
735 gets the integer point value for an entity key
738 int IntForKey( const entity_t *ent, const char *key )
743 k = ValueForKey( ent, key );
751 gets the floating point value for an entity key
754 vec_t FloatForKey( const entity_t *ent, const char *key )
759 k = ValueForKey( ent, key );
767 gets a 3-element vector value for an entity key
770 void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec )
777 k = ValueForKey( ent, key );
779 /* scanf into doubles, then assign, so it is vec_t size independent */
781 sscanf( k, "%lf %lf %lf", &v1, &v2, &v3 );
791 finds an entity target
794 entity_t *FindTargetEntity( const char *target )
800 /* walk entity list */
801 for( i = 0; i < numEntities; i++ )
803 n = ValueForKey( &entities[ i ], "targetname" );
804 if ( !strcmp( n, target ) )
805 return &entities[ i ];
815 GetEntityShadowFlags() - ydnar
816 gets an entity's shadow flags
817 note: does not set them to defaults if the keys are not found!
820 void GetEntityShadowFlags( const entity_t *ent, const entity_t *ent2, int *castShadows, int *recvShadows )
825 /* get cast shadows */
826 if( castShadows != NULL )
828 value = ValueForKey( ent, "_castShadows" );
829 if( value[ 0 ] == '\0' )
830 value = ValueForKey( ent, "_cs" );
831 if( value[ 0 ] == '\0' )
832 value = ValueForKey( ent2, "_castShadows" );
833 if( value[ 0 ] == '\0' )
834 value = ValueForKey( ent2, "_cs" );
835 if( value[ 0 ] != '\0' )
836 *castShadows = atoi( value );
840 if( recvShadows != NULL )
842 value = ValueForKey( ent, "_receiveShadows" );
843 if( value[ 0 ] == '\0' )
844 value = ValueForKey( ent, "_rs" );
845 if( value[ 0 ] == '\0' )
846 value = ValueForKey( ent2, "_receiveShadows" );
847 if( value[ 0 ] == '\0' )
848 value = ValueForKey( ent2, "_rs" );
849 if( value[ 0 ] != '\0' )
850 *recvShadows = atoi( value );