2 Copyright (C) 1999-2006 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
29 void GetLeafNums( void );
31 //=============================================================================
33 int bsp_version = Q3_BSP_VERSION;
36 dmodel_t dmodels[MAX_MAP_MODELS];
39 dshader_t dshaders[MAX_MAP_SHADERS];
42 char dentdata[MAX_MAP_ENTSTRING];
45 dleaf_t dleafs[MAX_MAP_LEAFS];
48 dplane_t dplanes[MAX_MAP_PLANES];
51 dnode_t dnodes[MAX_MAP_NODES];
54 int dleafsurfaces[MAX_MAP_LEAFFACES];
57 int dleafbrushes[MAX_MAP_LEAFBRUSHES];
60 dbrush_t dbrushes[MAX_MAP_BRUSHES];
63 dbrushside_t dbrushsides[MAX_MAP_BRUSHSIDES];
72 byte visBytes[MAX_MAP_VISIBILITY];
75 int numDrawVertsBuffer = 0;
76 drawVert_t *drawVerts = NULL;
79 int drawIndexes[MAX_MAP_DRAW_INDEXES];
82 int numDrawSurfacesBuffer = 0;
83 dsurface_t *drawSurfaces = NULL;
86 dfog_t dfogs[MAX_MAP_FOGS];
88 void SetLightBytes( int n ){
89 if ( lightBytes != 0 ) {
99 lightBytes = safe_malloc_info( numLightBytes, "SetLightBytes" );
101 memset( lightBytes, 0, numLightBytes );
104 void SetGridPoints( int n ){
105 if ( gridData != 0 ) {
115 gridData = safe_malloc_info( numGridPoints * 8, "SetGridPoints" );
117 memset( gridData, 0, numGridPoints * 8 );
123 if ( drawVerts == 0 ) {
124 numDrawVertsBuffer = MAX_MAP_DRAW_VERTS / 37;
126 drawVerts = safe_malloc_info( sizeof( drawVert_t ) * numDrawVertsBuffer, "IncDrawVerts" );
129 else if ( numDrawVerts > numDrawVertsBuffer ) {
130 numDrawVertsBuffer *= 3; // multiply by 1.5
131 numDrawVertsBuffer /= 2;
133 if ( numDrawVertsBuffer > MAX_MAP_DRAW_VERTS ) {
134 numDrawVertsBuffer = MAX_MAP_DRAW_VERTS;
137 drawVerts = realloc( drawVerts, sizeof( drawVert_t ) * numDrawVertsBuffer );
140 Error( "realloc() failed (IncDrawVerts)" );
144 memset( drawVerts + ( numDrawVerts - 1 ), 0, sizeof( drawVert_t ) );
147 void SetDrawVerts( int n ){
148 if ( drawVerts != 0 ) {
153 numDrawVertsBuffer = numDrawVerts;
155 drawVerts = safe_malloc_info( sizeof( drawVert_t ) * numDrawVertsBuffer, "IncDrawVerts" );
157 memset( drawVerts, 0, n * sizeof( drawVert_t ) );
160 void SetDrawSurfacesBuffer(){
161 if ( drawSurfaces != 0 ) {
162 free( drawSurfaces );
165 numDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
167 drawSurfaces = safe_malloc_info( sizeof( dsurface_t ) * numDrawSurfacesBuffer, "IncDrawSurfaces" );
169 memset( drawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof( drawVert_t ) );
172 void SetDrawSurfaces( int n ){
173 if ( drawSurfaces != 0 ) {
174 free( drawSurfaces );
178 numDrawSurfacesBuffer = numDrawSurfaces;
180 drawSurfaces = safe_malloc_info( sizeof( dsurface_t ) * numDrawSurfacesBuffer, "IncDrawSurfaces" );
182 memset( drawSurfaces, 0, n * sizeof( drawVert_t ) );
185 void BspFilesCleanup(){
186 if ( drawVerts != 0 ) {
189 if ( drawSurfaces != 0 ) {
190 free( drawSurfaces );
192 if ( lightBytes != 0 ) {
195 if ( gridData != 0 ) {
200 //=============================================================================
206 If all values are 32 bits, this can be used to swap everything
209 void SwapBlock( int *block, int sizeOfBlock ) {
213 for ( i = 0 ; i < sizeOfBlock ; i++ ) {
214 block[i] = LittleLong( block[i] );
222 Byte swaps all data in a bsp file.
225 void SwapBSPFile( void ) {
229 SwapBlock( (int *)dmodels, nummodels * sizeof( dmodels[0] ) );
231 // shaders (don't swap the name)
232 for ( i = 0 ; i < numShaders ; i++ ) {
233 dshaders[i].contentFlags = LittleLong( dshaders[i].contentFlags );
234 dshaders[i].surfaceFlags = LittleLong( dshaders[i].surfaceFlags );
238 SwapBlock( (int *)dplanes, numplanes * sizeof( dplanes[0] ) );
241 SwapBlock( (int *)dnodes, numnodes * sizeof( dnodes[0] ) );
244 SwapBlock( (int *)dleafs, numleafs * sizeof( dleafs[0] ) );
247 SwapBlock( (int *)dleafsurfaces, numleafsurfaces * sizeof( dleafsurfaces[0] ) );
250 SwapBlock( (int *)dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) );
253 SwapBlock( (int *)dbrushes, numbrushes * sizeof( dbrushes[0] ) );
256 SwapBlock( (int *)dbrushsides, numbrushsides * sizeof( dbrushsides[0] ) );
259 ( (int *)&visBytes )[0] = LittleLong( ( (int *)&visBytes )[0] );
260 ( (int *)&visBytes )[1] = LittleLong( ( (int *)&visBytes )[1] );
262 // drawverts (don't swap colors )
263 for ( i = 0 ; i < numDrawVerts ; i++ ) {
264 drawVerts[i].lightmap[0] = LittleFloat( drawVerts[i].lightmap[0] );
265 drawVerts[i].lightmap[1] = LittleFloat( drawVerts[i].lightmap[1] );
266 drawVerts[i].st[0] = LittleFloat( drawVerts[i].st[0] );
267 drawVerts[i].st[1] = LittleFloat( drawVerts[i].st[1] );
268 drawVerts[i].xyz[0] = LittleFloat( drawVerts[i].xyz[0] );
269 drawVerts[i].xyz[1] = LittleFloat( drawVerts[i].xyz[1] );
270 drawVerts[i].xyz[2] = LittleFloat( drawVerts[i].xyz[2] );
271 drawVerts[i].normal[0] = LittleFloat( drawVerts[i].normal[0] );
272 drawVerts[i].normal[1] = LittleFloat( drawVerts[i].normal[1] );
273 drawVerts[i].normal[2] = LittleFloat( drawVerts[i].normal[2] );
277 SwapBlock( (int *)drawIndexes, numDrawIndexes * sizeof( drawIndexes[0] ) );
280 SwapBlock( (int *)drawSurfaces, numDrawSurfaces * sizeof( drawSurfaces[0] ) );
283 for ( i = 0 ; i < numFogs ; i++ ) {
284 dfogs[i].brushNum = LittleLong( dfogs[i].brushNum );
285 dfogs[i].visibleSide = LittleLong( dfogs[i].visibleSide );
296 int GetLumpElements( dheader_t *header, int lump, int size ) {
297 int length = header->lumps[lump].filelen;
299 if ( length % size ) {
300 Error( "LoadBSPFile: odd lump size" );
303 return length / size;
311 int CopyLump( dheader_t *header, int lump, void *dest, int size ) {
314 length = header->lumps[lump].filelen;
315 ofs = header->lumps[lump].fileofs;
321 if ( length % size ) {
322 Error( "LoadBSPFile: odd lump size" );
325 memcpy( dest, (byte *)header + ofs, length );
327 return length / size;
335 void LoadBSPFile( const char *filename ) {
338 // load the file header
339 LoadFile( filename, (void **)&header );
342 SwapBlock( (int *)header, sizeof( *header ) );
344 if ( header->ident != BSP_IDENT ) {
345 Error( "%s is not a IBSP file", filename );
347 if ( header->version != bsp_version ) {
348 Error( "%s is version %i, not %i", filename, header->version, bsp_version );
351 numShaders = CopyLump( header, LUMP_SHADERS, dshaders, sizeof( dshader_t ) );
352 nummodels = CopyLump( header, LUMP_MODELS, dmodels, sizeof( dmodel_t ) );
353 numplanes = CopyLump( header, LUMP_PLANES, dplanes, sizeof( dplane_t ) );
354 numleafs = CopyLump( header, LUMP_LEAFS, dleafs, sizeof( dleaf_t ) );
355 numnodes = CopyLump( header, LUMP_NODES, dnodes, sizeof( dnode_t ) );
356 numleafsurfaces = CopyLump( header, LUMP_LEAFSURFACES, dleafsurfaces, sizeof( dleafsurfaces[0] ) );
357 numleafbrushes = CopyLump( header, LUMP_LEAFBRUSHES, dleafbrushes, sizeof( dleafbrushes[0] ) );
358 numbrushes = CopyLump( header, LUMP_BRUSHES, dbrushes, sizeof( dbrush_t ) );
359 numbrushsides = CopyLump( header, LUMP_BRUSHSIDES, dbrushsides, sizeof( dbrushside_t ) );
360 numDrawVerts = GetLumpElements( header, LUMP_DRAWVERTS, sizeof( drawVert_t ) );
361 SetDrawVerts( numDrawVerts );
362 CopyLump( header, LUMP_DRAWVERTS, drawVerts, sizeof( drawVert_t ) );
363 numDrawSurfaces = GetLumpElements( header, LUMP_SURFACES, sizeof( dsurface_t ) );
364 SetDrawSurfaces( numDrawSurfaces );
365 numDrawSurfaces = CopyLump( header, LUMP_SURFACES, drawSurfaces, sizeof( dsurface_t ) );
366 numFogs = CopyLump( header, LUMP_FOGS, dfogs, sizeof( dfog_t ) );
367 numDrawIndexes = CopyLump( header, LUMP_DRAWINDEXES, drawIndexes, sizeof( drawIndexes[0] ) );
369 numVisBytes = CopyLump( header, LUMP_VISIBILITY, visBytes, 1 );
370 numLightBytes = GetLumpElements( header, LUMP_LIGHTMAPS, 1 );
371 SetLightBytes( numLightBytes );
372 CopyLump( header, LUMP_LIGHTMAPS, lightBytes, 1 );
373 entdatasize = CopyLump( header, LUMP_ENTITIES, dentdata, 1 );
375 numGridPoints = GetLumpElements( header, LUMP_LIGHTGRID, 8 );
376 SetGridPoints( numGridPoints );
377 CopyLump( header, LUMP_LIGHTGRID, gridData, 8 );
380 free( header ); // everything has been copied out
387 //============================================================================
394 void AddLump( FILE *bspfile, dheader_t *header, int lumpnum, const void *data, int len ) {
397 lump = &header->lumps[lumpnum];
399 lump->fileofs = LittleLong( ftell( bspfile ) );
400 lump->filelen = LittleLong( len );
401 SafeWrite( bspfile, data, ( len + 3 ) & ~3 );
408 Swaps the bsp file in place, so it should not be referenced again
411 void WriteBSPFile( const char *filename ) {
412 dheader_t outheader, *header;
416 memset( header, 0, sizeof( dheader_t ) );
420 header->ident = LittleLong( BSP_IDENT );
421 header->version = LittleLong( bsp_version );
423 bspfile = SafeOpenWrite( filename );
424 SafeWrite( bspfile, header, sizeof( dheader_t ) ); // overwritten later
426 AddLump( bspfile, header, LUMP_SHADERS, dshaders, numShaders * sizeof( dshader_t ) );
427 AddLump( bspfile, header, LUMP_PLANES, dplanes, numplanes * sizeof( dplane_t ) );
428 AddLump( bspfile, header, LUMP_LEAFS, dleafs, numleafs * sizeof( dleaf_t ) );
429 AddLump( bspfile, header, LUMP_NODES, dnodes, numnodes * sizeof( dnode_t ) );
430 AddLump( bspfile, header, LUMP_BRUSHES, dbrushes, numbrushes * sizeof( dbrush_t ) );
431 AddLump( bspfile, header, LUMP_BRUSHSIDES, dbrushsides, numbrushsides * sizeof( dbrushside_t ) );
432 AddLump( bspfile, header, LUMP_LEAFSURFACES, dleafsurfaces, numleafsurfaces * sizeof( dleafsurfaces[0] ) );
433 AddLump( bspfile, header, LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) );
434 AddLump( bspfile, header, LUMP_MODELS, dmodels, nummodels * sizeof( dmodel_t ) );
435 AddLump( bspfile, header, LUMP_DRAWVERTS, drawVerts, numDrawVerts * sizeof( drawVert_t ) );
436 AddLump( bspfile, header, LUMP_SURFACES, drawSurfaces, numDrawSurfaces * sizeof( dsurface_t ) );
437 AddLump( bspfile, header, LUMP_VISIBILITY, visBytes, numVisBytes );
438 AddLump( bspfile, header, LUMP_LIGHTMAPS, lightBytes, numLightBytes );
439 AddLump( bspfile, header, LUMP_LIGHTGRID, gridData, 8 * numGridPoints );
440 AddLump( bspfile, header, LUMP_ENTITIES, dentdata, entdatasize );
441 AddLump( bspfile, header, LUMP_FOGS, dfogs, numFogs * sizeof( dfog_t ) );
442 AddLump( bspfile, header, LUMP_DRAWINDEXES, drawIndexes, numDrawIndexes * sizeof( drawIndexes[0] ) );
444 fseek( bspfile, 0, SEEK_SET );
445 SafeWrite( bspfile, header, sizeof( dheader_t ) );
449 //============================================================================
455 Dumps info about current file
458 void PrintBSPFileSizes( void ) {
459 if ( !num_entities ) {
463 Sys_Printf( "%6i models %7i\n"
464 ,nummodels, (int)( nummodels * sizeof( dmodel_t ) ) );
465 Sys_Printf( "%6i shaders %7i\n"
466 ,numShaders, (int)( numShaders * sizeof( dshader_t ) ) );
467 Sys_Printf( "%6i brushes %7i\n"
468 ,numbrushes, (int)( numbrushes * sizeof( dbrush_t ) ) );
469 Sys_Printf( "%6i brushsides %7i\n"
470 ,numbrushsides, (int)( numbrushsides * sizeof( dbrushside_t ) ) );
471 Sys_Printf( "%6i fogs %7i\n"
472 ,numFogs, (int)( numFogs * sizeof( dfog_t ) ) );
473 Sys_Printf( "%6i planes %7i\n"
474 ,numplanes, (int)( numplanes * sizeof( dplane_t ) ) );
475 Sys_Printf( "%6i entdata %7i\n", num_entities, entdatasize );
479 Sys_Printf( "%6i nodes %7i\n"
480 ,numnodes, (int)( numnodes * sizeof( dnode_t ) ) );
481 Sys_Printf( "%6i leafs %7i\n"
482 ,numleafs, (int)( numleafs * sizeof( dleaf_t ) ) );
483 Sys_Printf( "%6i leafsurfaces %7i\n"
484 ,numleafsurfaces, (int)( numleafsurfaces * sizeof( dleafsurfaces[0] ) ) );
485 Sys_Printf( "%6i leafbrushes %7i\n"
486 ,numleafbrushes, (int)( numleafbrushes * sizeof( dleafbrushes[0] ) ) );
487 Sys_Printf( "%6i drawverts %7i\n"
488 ,numDrawVerts, (int)( numDrawVerts * sizeof( drawVerts[0] ) ) );
489 Sys_Printf( "%6i drawindexes %7i\n"
490 ,numDrawIndexes, (int)( numDrawIndexes * sizeof( drawIndexes[0] ) ) );
491 Sys_Printf( "%6i drawsurfaces %7i\n"
492 ,numDrawSurfaces, (int)( numDrawSurfaces * sizeof( drawSurfaces[0] ) ) );
494 Sys_Printf( "%6i lightmaps %7i\n"
495 ,numLightBytes / ( LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3 ), numLightBytes );
496 Sys_Printf( " visibility %7i\n"
501 //============================================
504 entity_t entities[MAX_MAP_ENTITIES];
506 void StripTrailing( char *e ) {
509 s = e + strlen( e ) - 1;
510 while ( s >= e && *s <= 32 )
522 epair_t *ParseEpair( void ) {
525 e = safe_malloc( sizeof( epair_t ) );
526 memset( e, 0, sizeof( epair_t ) );
528 if ( strlen( token ) >= MAX_KEY - 1 ) {
529 Error( "ParseEpar: token too long" );
531 e->key = copystring( token );
533 if ( strlen( token ) >= MAX_VALUE - 1 ) {
534 Error( "ParseEpar: token too long" );
536 e->value = copystring( token );
538 // strip trailing spaces that sometimes get accidentally
539 // added in the editor
540 StripTrailing( e->key );
541 StripTrailing( e->value );
552 qboolean ParseEntity( void ) {
556 if ( !GetToken( qtrue ) ) {
560 if ( strcmp( token, "{" ) ) {
561 Error( "ParseEntity: { not found" );
563 if ( num_entities == MAX_MAP_ENTITIES ) {
564 Error( "num_entities == MAX_MAP_ENTITIES" );
566 mapent = &entities[num_entities];
570 if ( !GetToken( qtrue ) ) {
571 Error( "ParseEntity: EOF without closing brace" );
573 if ( !strcmp( token, "}" ) ) {
577 e->next = mapent->epairs;
588 Parses the dentdata string into entities
591 void ParseEntities( void ) {
593 ParseFromMemory( dentdata, entdatasize );
595 while ( ParseEntity() ) {
604 Generates the dentdata string from all the entities
605 This allows the utilities to add or remove key/value pairs
606 to the data created by the map editor.
609 void UnparseEntities( void ) {
614 char key[1024], value[1024];
620 for ( i = 0 ; i < num_entities ; i++ ) {
621 ep = entities[i].epairs;
623 continue; // ent got removed
629 for ( ep = entities[i].epairs ; ep ; ep = ep->next ) {
630 strcpy( key, ep->key );
631 StripTrailing( key );
632 strcpy( value, ep->value );
633 StripTrailing( value );
635 sprintf( line, "\"%s\" \"%s\"\n", key, value );
637 end += strlen( line );
642 if ( end > buf + MAX_MAP_ENTSTRING ) {
643 Error( "Entity text too long" );
646 entdatasize = end - buf + 1;
649 void PrintEntity( const entity_t *ent ) {
652 Sys_Printf( "------- entity %p -------\n", ent );
653 for ( ep = ent->epairs ; ep ; ep = ep->next ) {
654 Sys_Printf( "%s = %s\n", ep->key, ep->value );
659 void SetKeyValue( entity_t *ent, const char *key, const char *value ) {
662 for ( ep = ent->epairs ; ep ; ep = ep->next ) {
663 if ( !strcmp( ep->key, key ) ) {
665 ep->value = copystring( value );
669 ep = safe_malloc( sizeof( *ep ) );
670 ep->next = ent->epairs;
672 ep->key = copystring( key );
673 ep->value = copystring( value );
676 const char *ValueForKey( const entity_t *ent, const char *key ) {
679 for ( ep = ent->epairs ; ep ; ep = ep->next ) {
680 if ( !strcmp( ep->key, key ) ) {
687 vec_t FloatForKey( const entity_t *ent, const char *key ) {
690 k = ValueForKey( ent, key );
694 void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec ) {
698 k = ValueForKey( ent, key );
700 // scanf into doubles, then assign, so it is vec_t size independent
702 sscanf( k, "%lf %lf %lf", &v1, &v2, &v3 );