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_IBSP_C
42 /* -------------------------------------------------------------------------------
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.
47 ------------------------------------------------------------------------------- */
50 #define LUMP_ENTITIES 0
51 #define LUMP_SHADERS 1
55 #define LUMP_LEAFSURFACES 5
56 #define LUMP_LEAFBRUSHES 6
58 #define LUMP_BRUSHES 8
59 #define LUMP_BRUSHSIDES 9
60 #define LUMP_DRAWVERTS 10
61 #define LUMP_DRAWINDEXES 11
63 #define LUMP_SURFACES 13
64 #define LUMP_LIGHTMAPS 14
65 #define LUMP_LIGHTGRID 15
66 #define LUMP_VISIBILITY 16
67 #define LUMP_ADVERTISEMENTS 17
68 #define HEADER_LUMPS 18
77 bspLump_t lumps[ HEADER_LUMPS ];
92 static void CopyBrushSidesLump( ibspHeader_t *header ){
99 numBSPBrushSides = GetLumpElements( (bspHeader_t*) header, LUMP_BRUSHSIDES, sizeof( *in ) );
102 in = GetLump( (bspHeader_t*) header, LUMP_BRUSHSIDES );
103 for ( i = 0; i < numBSPBrushSides; i++ )
105 AUTOEXPAND_BY_REALLOC( bspBrushSides, i, allocatedBSPBrushSides, 1024 );
106 out = &bspBrushSides[i];
107 out->planeNum = in->planeNum;
108 out->shaderNum = in->shaderNum;
109 out->surfaceNum = -1;
115 static void AddBrushSidesLump( FILE *file, ibspHeader_t *header ){
118 ibspBrushSide_t *buffer, *out;
121 /* allocate output buffer */
122 size = numBSPBrushSides * sizeof( *buffer );
123 buffer = safe_malloc0( size );
128 for ( i = 0; i < numBSPBrushSides; i++ )
130 out->planeNum = in->planeNum;
131 out->shaderNum = in->shaderNum;
137 AddLump( file, (bspHeader_t*) header, LUMP_BRUSHSIDES, buffer, size );
146 typedef struct ibspDrawSurface_s
159 int lightmapX, lightmapY;
160 int lightmapWidth, lightmapHeight;
162 vec3_t lightmapOrigin;
163 vec3_t lightmapVecs[ 3 ];
171 static void CopyDrawSurfacesLump( ibspHeader_t *header ){
173 ibspDrawSurface_t *in;
174 bspDrawSurface_t *out;
178 numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( *in ) );
179 SetDrawSurfaces( numBSPDrawSurfaces );
182 in = GetLump( (bspHeader_t*) header, LUMP_SURFACES );
183 out = bspDrawSurfaces;
184 for ( i = 0; i < numBSPDrawSurfaces; i++ )
186 out->shaderNum = in->shaderNum;
187 out->fogNum = in->fogNum;
188 out->surfaceType = in->surfaceType;
189 out->firstVert = in->firstVert;
190 out->numVerts = in->numVerts;
191 out->firstIndex = in->firstIndex;
192 out->numIndexes = in->numIndexes;
194 out->lightmapStyles[ 0 ] = LS_NORMAL;
195 out->vertexStyles[ 0 ] = LS_NORMAL;
196 out->lightmapNum[ 0 ] = in->lightmapNum;
197 out->lightmapX[ 0 ] = in->lightmapX;
198 out->lightmapY[ 0 ] = in->lightmapY;
200 for ( j = 1; j < MAX_LIGHTMAPS; j++ )
202 out->lightmapStyles[ j ] = LS_NONE;
203 out->vertexStyles[ j ] = LS_NONE;
204 out->lightmapNum[ j ] = -3;
205 out->lightmapX[ j ] = 0;
206 out->lightmapY[ j ] = 0;
209 out->lightmapWidth = in->lightmapWidth;
210 out->lightmapHeight = in->lightmapHeight;
212 VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
213 VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
214 VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
215 VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
217 out->patchWidth = in->patchWidth;
218 out->patchHeight = in->patchHeight;
226 static void AddDrawSurfacesLump( FILE *file, ibspHeader_t *header ){
228 bspDrawSurface_t *in;
229 ibspDrawSurface_t *buffer, *out;
232 /* allocate output buffer */
233 size = numBSPDrawSurfaces * sizeof( *buffer );
234 buffer = safe_malloc0( size );
237 in = bspDrawSurfaces;
239 for ( i = 0; i < numBSPDrawSurfaces; i++ )
241 out->shaderNum = in->shaderNum;
242 out->fogNum = in->fogNum;
243 out->surfaceType = in->surfaceType;
244 out->firstVert = in->firstVert;
245 out->numVerts = in->numVerts;
246 out->firstIndex = in->firstIndex;
247 out->numIndexes = in->numIndexes;
249 out->lightmapNum = in->lightmapNum[ 0 ];
250 out->lightmapX = in->lightmapX[ 0 ];
251 out->lightmapY = in->lightmapY[ 0 ];
252 out->lightmapWidth = in->lightmapWidth;
253 out->lightmapHeight = in->lightmapHeight;
255 VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
256 VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
257 VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
258 VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
260 out->patchWidth = in->patchWidth;
261 out->patchHeight = in->patchHeight;
268 AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, buffer, size );
288 static void CopyDrawVertsLump( ibspHeader_t *header ){
295 numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( *in ) );
296 SetDrawVerts( numBSPDrawVerts );
299 in = GetLump( (bspHeader_t*) header, LUMP_DRAWVERTS );
301 for ( i = 0; i < numBSPDrawVerts; i++ )
303 VectorCopy( in->xyz, out->xyz );
304 out->st[ 0 ] = in->st[ 0 ];
305 out->st[ 1 ] = in->st[ 1 ];
307 out->lightmap[ 0 ][ 0 ] = in->lightmap[ 0 ];
308 out->lightmap[ 0 ][ 1 ] = in->lightmap[ 1 ];
310 VectorCopy( in->normal, out->normal );
312 out->color[ 0 ][ 0 ] = in->color[ 0 ];
313 out->color[ 0 ][ 1 ] = in->color[ 1 ];
314 out->color[ 0 ][ 2 ] = in->color[ 2 ];
315 out->color[ 0 ][ 3 ] = in->color[ 3 ];
323 static void AddDrawVertsLump( FILE *file, ibspHeader_t *header ){
326 ibspDrawVert_t *buffer, *out;
329 /* allocate output buffer */
330 size = numBSPDrawVerts * sizeof( *buffer );
331 buffer = safe_malloc0( size );
336 for ( i = 0; i < numBSPDrawVerts; i++ )
338 VectorCopy( in->xyz, out->xyz );
339 out->st[ 0 ] = in->st[ 0 ];
340 out->st[ 1 ] = in->st[ 1 ];
342 out->lightmap[ 0 ] = in->lightmap[ 0 ][ 0 ];
343 out->lightmap[ 1 ] = in->lightmap[ 0 ][ 1 ];
345 VectorCopy( in->normal, out->normal );
347 out->color[ 0 ] = in->color[ 0 ][ 0 ];
348 out->color[ 1 ] = in->color[ 0 ][ 1 ];
349 out->color[ 2 ] = in->color[ 0 ][ 2 ];
350 out->color[ 3 ] = in->color[ 0 ][ 3 ];
357 AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, buffer, size );
375 static void CopyLightGridLumps( ibspHeader_t *header ){
382 numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTGRID, sizeof( *in ) );
384 /* allocate buffer */
385 bspGridPoints = safe_malloc0( numBSPGridPoints * sizeof( *bspGridPoints ) );
388 in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
390 for ( i = 0; i < numBSPGridPoints; i++ )
392 for ( j = 0; j < MAX_LIGHTMAPS; j++ )
394 VectorCopy( in->ambient, out->ambient[ j ] );
395 VectorCopy( in->directed, out->directed[ j ] );
396 out->styles[ j ] = LS_NONE;
399 out->styles[ 0 ] = LS_NORMAL;
401 out->latLong[ 0 ] = in->latLong[ 0 ];
402 out->latLong[ 1 ] = in->latLong[ 1 ];
410 static void AddLightGridLumps( FILE *file, ibspHeader_t *header ){
413 ibspGridPoint_t *buffer, *out;
417 if ( bspGridPoints == NULL ) {
421 /* allocate temporary buffer */
422 buffer = safe_malloc( numBSPGridPoints * sizeof( *out ) );
427 for ( i = 0; i < numBSPGridPoints; i++ )
429 VectorCopy( in->ambient[ 0 ], out->ambient );
430 VectorCopy( in->directed[ 0 ], out->directed );
432 out->latLong[ 0 ] = in->latLong[ 0 ];
433 out->latLong[ 1 ] = in->latLong[ 1 ];
440 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, buffer, ( numBSPGridPoints * sizeof( *out ) ) );
442 /* free buffer (ydnar 2002-10-22: [bug 641] thanks Rap70r! */
448 loads a quake 3 bsp file into memory
451 void LoadIBSPFile( const char *filename ){
452 ibspHeader_t *header;
455 /* load the file header */
456 LoadFile( filename, (void**) &header );
458 /* swap the header (except the first 4 bytes) */
459 SwapBlock( (int*) ( (byte*) header + sizeof( int ) ), sizeof( *header ) - sizeof( int ) );
461 /* make sure it matches the format we're trying to load */
462 if ( force == qfalse && *( (int*) header->ident ) != *( (int*) game->bspIdent ) ) {
463 Error( "%s is not a %s file", filename, game->bspIdent );
465 if ( force == qfalse && header->version != game->bspVersion ) {
466 Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
469 /* load/convert lumps */
470 numBSPShaders = CopyLump_Allocate( (bspHeader_t*) header, LUMP_SHADERS, (void **) &bspShaders, sizeof( bspShader_t ), &allocatedBSPShaders );
472 numBSPModels = CopyLump_Allocate( (bspHeader_t*) header, LUMP_MODELS, (void **) &bspModels, sizeof( bspModel_t ), &allocatedBSPModels );
474 numBSPPlanes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_PLANES, (void **) &bspPlanes, sizeof( bspPlane_t ), &allocatedBSPPlanes );
476 numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) ); // TODO fix overflow
478 numBSPNodes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_NODES, (void **) &bspNodes, sizeof( bspNode_t ), &allocatedBSPNodes );
480 numBSPLeafSurfaces = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFSURFACES, (void **) &bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ), &allocatedBSPLeafSurfaces );
482 numBSPLeafBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFBRUSHES, (void **) &bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ), &allocatedBSPLeafBrushes );
484 numBSPBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_BRUSHES, (void **) &bspBrushes, sizeof( bspBrush_t ), &allocatedBSPLeafBrushes );
486 CopyBrushSidesLump( header );
488 CopyDrawVertsLump( header );
490 CopyDrawSurfacesLump( header );
492 numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFog_t ) ); // TODO fix overflow
494 numBSPDrawIndexes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_DRAWINDEXES, (void **) &bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ), &allocatedBSPDrawIndexes );
496 numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 ); // TODO fix overflow
498 numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 ); // TODO change to CopyLump_Allocate
499 bspLightBytes = safe_malloc( numBSPLightBytes );
500 CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
502 bspEntDataSize = CopyLump_Allocate( (bspHeader_t*) header, LUMP_ENTITIES, (void **) &bspEntData, 1, &allocatedBSPEntData );
504 CopyLightGridLumps( header );
507 if ( header->version == 47 ) { // quake live's bsp version
508 numBSPAds = CopyLump( (bspHeader_t*) header, LUMP_ADVERTISEMENTS, bspAds, sizeof( bspAdvertisement_t ) );
514 /* free the file buffer */
519 PartialLoadIBSPFile()
520 loads a part of quake 3 bsp file, required by packer, into memory
523 void PartialLoadIBSPFile( const char *filename ){
524 ibspHeader_t *header;
527 /* load the file header */
528 LoadFile( filename, (void**) &header );
530 /* swap the header (except the first 4 bytes) */
531 SwapBlock( (int*) ( (byte*) header + sizeof( int ) ), sizeof( *header ) - sizeof( int ) );
533 /* make sure it matches the format we're trying to load */
534 if ( force == qfalse && *( (int*) header->ident ) != *( (int*) game->bspIdent ) ) {
535 Error( "%s is not a %s file", filename, game->bspIdent );
537 if ( force == qfalse && header->version != game->bspVersion ) {
538 Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
541 /* load/convert lumps */
542 numBSPShaders = CopyLump_Allocate( (bspHeader_t*) header, LUMP_SHADERS, (void **) &bspShaders, sizeof( bspShader_t ), &allocatedBSPShaders );
544 CopyDrawSurfacesLump( header );
546 bspEntDataSize = CopyLump_Allocate( (bspHeader_t*) header, LUMP_ENTITIES, (void **) &bspEntData, 1, &allocatedBSPEntData );
548 /* free the file buffer */
554 writes an id bsp file
557 void WriteIBSPFile( const char *filename ){
558 ibspHeader_t outheader, *header;
566 memset( header, 0, sizeof( *header ) );
571 *( (int*) (bspHeader_t*) header->ident ) = *( (int*) game->bspIdent );
572 header->version = LittleLong( game->bspVersion );
574 /* write initial header */
575 file = SafeOpenWrite( filename );
576 SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) ); /* overwritten later */
578 /* add marker lump */
579 const char marker[] = "I LOVE MY Q3MAP2";
580 AddLump( file, header, 0, marker, strlen( marker ) + 1 );
583 AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
584 AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
585 AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
586 AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
587 AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes * sizeof( bspBrush_t ) );
588 AddBrushSidesLump( file, header );
589 AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
590 AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
591 AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
592 AddDrawVertsLump( file, header );
593 AddDrawSurfacesLump( file, header );
594 AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
595 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
596 AddLightGridLumps( file, header );
597 AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
598 AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
599 AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
602 AddLump( file, (bspHeader_t*) header, LUMP_ADVERTISEMENTS, bspAds, numBSPAds * sizeof( bspAdvertisement_t ) );
605 size = ftell( file );
606 Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / ( 1024 * 1024 ), size );
608 /* write the completed header */
609 fseek( file, 0, SEEK_SET );
610 SafeWrite( file, header, sizeof( *header ) );