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_malloc( size );
124 memset( buffer, 0, size );
129 for ( i = 0; i < numBSPBrushSides; i++ )
131 out->planeNum = in->planeNum;
132 out->shaderNum = in->shaderNum;
138 AddLump( file, (bspHeader_t*) header, LUMP_BRUSHSIDES, buffer, size );
147 typedef struct ibspDrawSurface_s
160 int lightmapX, lightmapY;
161 int lightmapWidth, lightmapHeight;
163 vec3_t lightmapOrigin;
164 vec3_t lightmapVecs[ 3 ];
172 static void CopyDrawSurfacesLump( ibspHeader_t *header ){
174 ibspDrawSurface_t *in;
175 bspDrawSurface_t *out;
179 numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( *in ) );
180 SetDrawSurfaces( numBSPDrawSurfaces );
183 in = GetLump( (bspHeader_t*) header, LUMP_SURFACES );
184 out = bspDrawSurfaces;
185 for ( i = 0; i < numBSPDrawSurfaces; i++ )
187 out->shaderNum = in->shaderNum;
188 out->fogNum = in->fogNum;
189 out->surfaceType = in->surfaceType;
190 out->firstVert = in->firstVert;
191 out->numVerts = in->numVerts;
192 out->firstIndex = in->firstIndex;
193 out->numIndexes = in->numIndexes;
195 out->lightmapStyles[ 0 ] = LS_NORMAL;
196 out->vertexStyles[ 0 ] = LS_NORMAL;
197 out->lightmapNum[ 0 ] = in->lightmapNum;
198 out->lightmapX[ 0 ] = in->lightmapX;
199 out->lightmapY[ 0 ] = in->lightmapY;
201 for ( j = 1; j < MAX_LIGHTMAPS; j++ )
203 out->lightmapStyles[ j ] = LS_NONE;
204 out->vertexStyles[ j ] = LS_NONE;
205 out->lightmapNum[ j ] = -3;
206 out->lightmapX[ j ] = 0;
207 out->lightmapY[ j ] = 0;
210 out->lightmapWidth = in->lightmapWidth;
211 out->lightmapHeight = in->lightmapHeight;
213 VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
214 VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
215 VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
216 VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
218 out->patchWidth = in->patchWidth;
219 out->patchHeight = in->patchHeight;
227 static void AddDrawSurfacesLump( FILE *file, ibspHeader_t *header ){
229 bspDrawSurface_t *in;
230 ibspDrawSurface_t *buffer, *out;
233 /* allocate output buffer */
234 size = numBSPDrawSurfaces * sizeof( *buffer );
235 buffer = safe_malloc( size );
236 memset( buffer, 0, size );
239 in = bspDrawSurfaces;
241 for ( i = 0; i < numBSPDrawSurfaces; i++ )
243 out->shaderNum = in->shaderNum;
244 out->fogNum = in->fogNum;
245 out->surfaceType = in->surfaceType;
246 out->firstVert = in->firstVert;
247 out->numVerts = in->numVerts;
248 out->firstIndex = in->firstIndex;
249 out->numIndexes = in->numIndexes;
251 out->lightmapNum = in->lightmapNum[ 0 ];
252 out->lightmapX = in->lightmapX[ 0 ];
253 out->lightmapY = in->lightmapY[ 0 ];
254 out->lightmapWidth = in->lightmapWidth;
255 out->lightmapHeight = in->lightmapHeight;
257 VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
258 VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
259 VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
260 VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
262 out->patchWidth = in->patchWidth;
263 out->patchHeight = in->patchHeight;
270 AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, buffer, size );
290 static void CopyDrawVertsLump( ibspHeader_t *header ){
297 numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( *in ) );
298 SetDrawVerts( numBSPDrawVerts );
301 in = GetLump( (bspHeader_t*) header, LUMP_DRAWVERTS );
303 for ( i = 0; i < numBSPDrawVerts; i++ )
305 VectorCopy( in->xyz, out->xyz );
306 out->st[ 0 ] = in->st[ 0 ];
307 out->st[ 1 ] = in->st[ 1 ];
309 out->lightmap[ 0 ][ 0 ] = in->lightmap[ 0 ];
310 out->lightmap[ 0 ][ 1 ] = in->lightmap[ 1 ];
312 VectorCopy( in->normal, out->normal );
314 out->color[ 0 ][ 0 ] = in->color[ 0 ];
315 out->color[ 0 ][ 1 ] = in->color[ 1 ];
316 out->color[ 0 ][ 2 ] = in->color[ 2 ];
317 out->color[ 0 ][ 3 ] = in->color[ 3 ];
325 static void AddDrawVertsLump( FILE *file, ibspHeader_t *header ){
328 ibspDrawVert_t *buffer, *out;
331 /* allocate output buffer */
332 size = numBSPDrawVerts * sizeof( *buffer );
333 buffer = safe_malloc( size );
334 memset( buffer, 0, size );
339 for ( i = 0; i < numBSPDrawVerts; i++ )
341 VectorCopy( in->xyz, out->xyz );
342 out->st[ 0 ] = in->st[ 0 ];
343 out->st[ 1 ] = in->st[ 1 ];
345 out->lightmap[ 0 ] = in->lightmap[ 0 ][ 0 ];
346 out->lightmap[ 1 ] = in->lightmap[ 0 ][ 1 ];
348 VectorCopy( in->normal, out->normal );
350 out->color[ 0 ] = in->color[ 0 ][ 0 ];
351 out->color[ 1 ] = in->color[ 0 ][ 1 ];
352 out->color[ 2 ] = in->color[ 0 ][ 2 ];
353 out->color[ 3 ] = in->color[ 0 ][ 3 ];
360 AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, buffer, size );
378 static void CopyLightGridLumps( ibspHeader_t *header ){
385 numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTGRID, sizeof( *in ) );
387 /* allocate buffer */
388 bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
389 memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
392 in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
394 for ( i = 0; i < numBSPGridPoints; i++ )
396 for ( j = 0; j < MAX_LIGHTMAPS; j++ )
398 VectorCopy( in->ambient, out->ambient[ j ] );
399 VectorCopy( in->directed, out->directed[ j ] );
400 out->styles[ j ] = LS_NONE;
403 out->styles[ 0 ] = LS_NORMAL;
405 out->latLong[ 0 ] = in->latLong[ 0 ];
406 out->latLong[ 1 ] = in->latLong[ 1 ];
414 static void AddLightGridLumps( FILE *file, ibspHeader_t *header ){
417 ibspGridPoint_t *buffer, *out;
421 if ( bspGridPoints == NULL ) {
425 /* allocate temporary buffer */
426 buffer = safe_malloc( numBSPGridPoints * sizeof( *out ) );
431 for ( i = 0; i < numBSPGridPoints; i++ )
433 VectorCopy( in->ambient[ 0 ], out->ambient );
434 VectorCopy( in->directed[ 0 ], out->directed );
436 out->latLong[ 0 ] = in->latLong[ 0 ];
437 out->latLong[ 1 ] = in->latLong[ 1 ];
444 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, buffer, ( numBSPGridPoints * sizeof( *out ) ) );
446 /* free buffer (ydnar 2002-10-22: [bug 641] thanks Rap70r! */
452 loads a quake 3 bsp file into memory
455 void LoadIBSPFile( const char *filename ){
456 ibspHeader_t *header;
459 /* load the file header */
460 LoadFile( filename, (void**) &header );
462 /* swap the header (except the first 4 bytes) */
463 SwapBlock( (int*) ( (byte*) header + sizeof( int ) ), sizeof( *header ) - sizeof( int ) );
465 /* make sure it matches the format we're trying to load */
466 if ( force == qfalse && *( (int*) header->ident ) != *( (int*) game->bspIdent ) ) {
467 Error( "%s is not a %s file", filename, game->bspIdent );
469 if ( force == qfalse && header->version != game->bspVersion ) {
470 Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
473 /* load/convert lumps */
474 numBSPShaders = CopyLump_Allocate( (bspHeader_t*) header, LUMP_SHADERS, (void **) &bspShaders, sizeof( bspShader_t ), &allocatedBSPShaders );
476 numBSPModels = CopyLump_Allocate( (bspHeader_t*) header, LUMP_MODELS, (void **) &bspModels, sizeof( bspModel_t ), &allocatedBSPModels );
478 numBSPPlanes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_PLANES, (void **) &bspPlanes, sizeof( bspPlane_t ), &allocatedBSPPlanes );
480 numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) ); // TODO fix overflow
482 numBSPNodes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_NODES, (void **) &bspNodes, sizeof( bspNode_t ), &allocatedBSPNodes );
484 numBSPLeafSurfaces = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFSURFACES, (void **) &bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ), &allocatedBSPLeafSurfaces );
486 numBSPLeafBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFBRUSHES, (void **) &bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ), &allocatedBSPLeafBrushes );
488 numBSPBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_BRUSHES, (void **) &bspBrushes, sizeof( bspBrush_t ), &allocatedBSPLeafBrushes );
490 CopyBrushSidesLump( header );
492 CopyDrawVertsLump( header );
494 CopyDrawSurfacesLump( header );
496 numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFog_t ) ); // TODO fix overflow
498 numBSPDrawIndexes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_DRAWINDEXES, (void **) &bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ), &allocatedBSPDrawIndexes );
500 numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 ); // TODO fix overflow
502 numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 ); // TODO change to CopyLump_Allocate
503 bspLightBytes = safe_malloc( numBSPLightBytes );
504 CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
506 bspEntDataSize = CopyLump_Allocate( (bspHeader_t*) header, LUMP_ENTITIES, (void **) &bspEntData, 1, &allocatedBSPEntData );
508 CopyLightGridLumps( header );
511 if ( header->version == 47 ) { // quake live's bsp version
512 numBSPAds = CopyLump( (bspHeader_t*) header, LUMP_ADVERTISEMENTS, bspAds, sizeof( bspAdvertisement_t ) );
518 /* free the file buffer */
526 writes an id bsp file
529 void WriteIBSPFile( const char *filename ){
530 ibspHeader_t outheader, *header;
539 memset( header, 0, sizeof( *header ) );
544 *( (int*) (bspHeader_t*) header->ident ) = *( (int*) game->bspIdent );
545 header->version = LittleLong( game->bspVersion );
547 /* write initial header */
548 file = SafeOpenWrite( filename );
549 SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) ); /* overwritten later */
551 /* add marker lump */
553 sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
554 AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
557 AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
558 AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
559 AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
560 AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
561 AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes * sizeof( bspBrush_t ) );
562 AddBrushSidesLump( file, header );
563 AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
564 AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
565 AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
566 AddDrawVertsLump( file, header );
567 AddDrawSurfacesLump( file, header );
568 AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
569 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
570 AddLightGridLumps( file, header );
571 AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
572 AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
573 AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
576 AddLump( file, (bspHeader_t*) header, LUMP_ADVERTISEMENTS, bspAds, numBSPAds * sizeof( bspAdvertisement_t ) );
579 size = ftell( file );
580 Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / ( 1024 * 1024 ), size );
582 /* write the completed header */
583 fseek( file, 0, SEEK_SET );
584 SafeWrite( file, header, sizeof( *header ) );