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 )
100 numBSPBrushSides = GetLumpElements( (bspHeader_t*) header, LUMP_BRUSHSIDES, sizeof( *in ) );
103 in = GetLump( (bspHeader_t*) header, LUMP_BRUSHSIDES );
104 for( i = 0; i < numBSPBrushSides; i++ )
106 AUTOEXPAND_BY_REALLOC(bspBrushSides, i, allocatedBSPBrushSides, 1024);
107 out = &bspBrushSides[i];
108 out->planeNum = in->planeNum;
109 out->shaderNum = in->shaderNum;
110 out->surfaceNum = -1;
116 static void AddBrushSidesLump( FILE *file, ibspHeader_t *header )
120 ibspBrushSide_t *buffer, *out;
123 /* allocate output buffer */
124 size = numBSPBrushSides * sizeof( *buffer );
125 buffer = safe_malloc( size );
126 memset( buffer, 0, size );
131 for( i = 0; i < numBSPBrushSides; i++ )
133 out->planeNum = in->planeNum;
134 out->shaderNum = in->shaderNum;
140 AddLump( file, (bspHeader_t*) header, LUMP_BRUSHSIDES, buffer, size );
149 typedef struct ibspDrawSurface_s
162 int lightmapX, lightmapY;
163 int lightmapWidth, lightmapHeight;
165 vec3_t lightmapOrigin;
166 vec3_t lightmapVecs[ 3 ];
174 static void CopyDrawSurfacesLump( ibspHeader_t *header )
177 ibspDrawSurface_t *in;
178 bspDrawSurface_t *out;
182 numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( *in ) );
183 SetDrawSurfaces( numBSPDrawSurfaces );
186 in = GetLump( (bspHeader_t*) header, LUMP_SURFACES );
187 out = bspDrawSurfaces;
188 for( i = 0; i < numBSPDrawSurfaces; i++ )
190 out->shaderNum = in->shaderNum;
191 out->fogNum = in->fogNum;
192 out->surfaceType = in->surfaceType;
193 out->firstVert = in->firstVert;
194 out->numVerts = in->numVerts;
195 out->firstIndex = in->firstIndex;
196 out->numIndexes = in->numIndexes;
198 out->lightmapStyles[ 0 ] = LS_NORMAL;
199 out->vertexStyles[ 0 ] = LS_NORMAL;
200 out->lightmapNum[ 0 ] = in->lightmapNum;
201 out->lightmapX[ 0 ] = in->lightmapX;
202 out->lightmapY[ 0 ] = in->lightmapY;
204 for( j = 1; j < MAX_LIGHTMAPS; j++ )
206 out->lightmapStyles[ j ] = LS_NONE;
207 out->vertexStyles[ j ] = LS_NONE;
208 out->lightmapNum[ j ] = -3;
209 out->lightmapX[ j ] = 0;
210 out->lightmapY[ j ] = 0;
213 out->lightmapWidth = in->lightmapWidth;
214 out->lightmapHeight = in->lightmapHeight;
216 VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
217 VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
218 VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
219 VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
221 out->patchWidth = in->patchWidth;
222 out->patchHeight = in->patchHeight;
230 static void AddDrawSurfacesLump( FILE *file, ibspHeader_t *header )
233 bspDrawSurface_t *in;
234 ibspDrawSurface_t *buffer, *out;
237 /* allocate output buffer */
238 size = numBSPDrawSurfaces * sizeof( *buffer );
239 buffer = safe_malloc( size );
240 memset( buffer, 0, size );
243 in = bspDrawSurfaces;
245 for( i = 0; i < numBSPDrawSurfaces; i++ )
247 out->shaderNum = in->shaderNum;
248 out->fogNum = in->fogNum;
249 out->surfaceType = in->surfaceType;
250 out->firstVert = in->firstVert;
251 out->numVerts = in->numVerts;
252 out->firstIndex = in->firstIndex;
253 out->numIndexes = in->numIndexes;
255 out->lightmapNum = in->lightmapNum[ 0 ];
256 out->lightmapX = in->lightmapX[ 0 ];
257 out->lightmapY = in->lightmapY[ 0 ];
258 out->lightmapWidth = in->lightmapWidth;
259 out->lightmapHeight = in->lightmapHeight;
261 VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
262 VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
263 VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
264 VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
266 out->patchWidth = in->patchWidth;
267 out->patchHeight = in->patchHeight;
274 AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, buffer, size );
294 static void CopyDrawVertsLump( ibspHeader_t *header )
302 numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( *in ) );
303 SetDrawVerts( numBSPDrawVerts );
306 in = GetLump( (bspHeader_t*) header, LUMP_DRAWVERTS );
308 for( i = 0; i < numBSPDrawVerts; i++ )
310 VectorCopy( in->xyz, out->xyz );
311 out->st[ 0 ] = in->st[ 0 ];
312 out->st[ 1 ] = in->st[ 1 ];
314 out->lightmap[ 0 ][ 0 ] = in->lightmap[ 0 ];
315 out->lightmap[ 0 ][ 1 ] = in->lightmap[ 1 ];
317 VectorCopy( in->normal, out->normal );
319 out->color[ 0 ][ 0 ] = in->color[ 0 ];
320 out->color[ 0 ][ 1 ] = in->color[ 1 ];
321 out->color[ 0 ][ 2 ] = in->color[ 2 ];
322 out->color[ 0 ][ 3 ] = in->color[ 3 ];
330 static void AddDrawVertsLump( FILE *file, ibspHeader_t *header )
334 ibspDrawVert_t *buffer, *out;
337 /* allocate output buffer */
338 size = numBSPDrawVerts * sizeof( *buffer );
339 buffer = safe_malloc( size );
340 memset( buffer, 0, size );
345 for( i = 0; i < numBSPDrawVerts; i++ )
347 VectorCopy( in->xyz, out->xyz );
348 out->st[ 0 ] = in->st[ 0 ];
349 out->st[ 1 ] = in->st[ 1 ];
351 out->lightmap[ 0 ] = in->lightmap[ 0 ][ 0 ];
352 out->lightmap[ 1 ] = in->lightmap[ 0 ][ 1 ];
354 VectorCopy( in->normal, out->normal );
356 out->color[ 0 ] = in->color[ 0 ][ 0 ];
357 out->color[ 1 ] = in->color[ 0 ][ 1 ];
358 out->color[ 2 ] = in->color[ 0 ][ 2 ];
359 out->color[ 3 ] = in->color[ 0 ][ 3 ];
366 AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, buffer, size );
384 static void CopyLightGridLumps( ibspHeader_t *header )
392 numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTGRID, sizeof( *in ) );
394 /* allocate buffer */
395 bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
396 memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
399 in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
401 for( i = 0; i < numBSPGridPoints; i++ )
403 for( j = 0; j < MAX_LIGHTMAPS; j++ )
405 VectorCopy( in->ambient, out->ambient[ j ] );
406 VectorCopy( in->directed, out->directed[ j ] );
407 out->styles[ j ] = LS_NONE;
410 out->styles[ 0 ] = LS_NORMAL;
412 out->latLong[ 0 ] = in->latLong[ 0 ];
413 out->latLong[ 1 ] = in->latLong[ 1 ];
421 static void AddLightGridLumps( FILE *file, ibspHeader_t *header )
425 ibspGridPoint_t *buffer, *out;
429 if( bspGridPoints == NULL )
432 /* allocate temporary buffer */
433 buffer = safe_malloc( numBSPGridPoints * sizeof( *out ) );
438 for( i = 0; i < numBSPGridPoints; i++ )
440 VectorCopy( in->ambient[ 0 ], out->ambient );
441 VectorCopy( in->directed[ 0 ], out->directed );
443 out->latLong[ 0 ] = in->latLong[ 0 ];
444 out->latLong[ 1 ] = in->latLong[ 1 ];
451 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, buffer, (numBSPGridPoints * sizeof( *out )) );
453 /* free buffer (ydnar 2002-10-22: [bug 641] thanks Rap70r! */
459 loads a quake 3 bsp file into memory
462 void LoadIBSPFile( const char *filename )
464 ibspHeader_t *header;
467 /* load the file header */
468 LoadFile( filename, (void**) &header );
470 /* swap the header (except the first 4 bytes) */
471 SwapBlock( (int*) ((byte*) header + sizeof( int )), sizeof( *header ) - sizeof( int ) );
473 /* make sure it matches the format we're trying to load */
474 if( force == qfalse && *((int*) header->ident) != *((int*) game->bspIdent) )
475 Error( "%s is not a %s file", filename, game->bspIdent );
476 if( force == qfalse && header->version != game->bspVersion )
477 Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
479 /* load/convert lumps */
480 numBSPShaders = CopyLump_Allocate( (bspHeader_t*) header, LUMP_SHADERS, (void **) &bspShaders, sizeof( bspShader_t ), &allocatedBSPShaders );
482 numBSPModels = CopyLump_Allocate( (bspHeader_t*) header, LUMP_MODELS, (void **) &bspModels, sizeof( bspModel_t ), &allocatedBSPModels );
484 numBSPPlanes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_PLANES, (void **) &bspPlanes, sizeof( bspPlane_t ), &allocatedBSPPlanes );
486 numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) ); // TODO fix overflow
488 numBSPNodes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_NODES, (void **) &bspNodes, sizeof( bspNode_t ), &allocatedBSPNodes );
490 numBSPLeafSurfaces = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFSURFACES, (void **) &bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ), &allocatedBSPLeafSurfaces );
492 numBSPLeafBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFBRUSHES, (void **) &bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ), &allocatedBSPLeafBrushes );
494 numBSPBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_BRUSHES, (void **) &bspBrushes, sizeof( bspBrush_t ), &allocatedBSPLeafBrushes );
496 CopyBrushSidesLump( header );
498 CopyDrawVertsLump( header );
500 CopyDrawSurfacesLump( header );
502 numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFog_t ) ); // TODO fix overflow
504 numBSPDrawIndexes = CopyLump( (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ) );
506 numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 ); // TODO fix overflow
508 numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 ); // TODO change to CopyLump_Allocate
509 bspLightBytes = safe_malloc( numBSPLightBytes );
510 CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
512 bspEntDataSize = CopyLump_Allocate( (bspHeader_t*) header, LUMP_ENTITIES, (void **) &bspEntData, 1, &allocatedBSPEntData);
514 CopyLightGridLumps( header );
517 if(header->version == 47) // quake live's bsp version
518 numBSPAds = CopyLump( (bspHeader_t*) header, LUMP_ADVERTISEMENTS, bspAds, sizeof( bspAdvertisement_t ) );
522 /* free the file buffer */
530 writes an id bsp file
533 void WriteIBSPFile( const char *filename )
535 ibspHeader_t outheader, *header;
544 memset( header, 0, sizeof( *header ) );
549 *((int*) (bspHeader_t*) header->ident) = *((int*) game->bspIdent);
550 header->version = LittleLong( game->bspVersion );
552 /* write initial header */
553 file = SafeOpenWrite( filename );
554 SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) ); /* overwritten later */
556 /* add marker lump */
558 sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
559 AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
562 AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
563 AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
564 AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
565 AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
566 AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes*sizeof( bspBrush_t ) );
567 AddBrushSidesLump( file, header );
568 AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
569 AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
570 AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
571 AddDrawVertsLump( file, header );
572 AddDrawSurfacesLump( file, header );
573 AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
574 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
575 AddLightGridLumps( file, header );
576 AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
577 AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
578 AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
581 AddLump( file, (bspHeader_t*) header, LUMP_ADVERTISEMENTS, bspAds, numBSPAds * sizeof( bspAdvertisement_t ) );
584 size = ftell( file );
585 Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / (1024 * 1024), size );
587 /* write the completed header */
588 fseek( file, 0, SEEK_SET );
589 SafeWrite( file, header, sizeof( *header ) );