2 Copyright (C) 1999-2007 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
21 ----------------------------------------------------------------------------------
23 This code has been altered significantly from its original form, to support
24 several games based on the Quake III Arena engine, in the form of "Q3Map2."
26 ------------------------------------------------------------------------------- */
31 #define BSPFILE_IBSP_C
41 /* -------------------------------------------------------------------------------
43 this file handles translating the bsp file format used by quake 3, rtcw, and ef
44 into the abstracted bsp file used by q3map2.
46 ------------------------------------------------------------------------------- */
49 #define LUMP_ENTITIES 0
50 #define LUMP_SHADERS 1
54 #define LUMP_LEAFSURFACES 5
55 #define LUMP_LEAFBRUSHES 6
57 #define LUMP_BRUSHES 8
58 #define LUMP_BRUSHSIDES 9
59 #define LUMP_DRAWVERTS 10
60 #define LUMP_DRAWINDEXES 11
62 #define LUMP_SURFACES 13
63 #define LUMP_LIGHTMAPS 14
64 #define LUMP_LIGHTGRID 15
65 #define LUMP_VISIBILITY 16
66 #define HEADER_LUMPS 17
75 bspLump_t lumps[ HEADER_LUMPS ];
90 static void CopyBrushSidesLump( ibspHeader_t *header )
98 numBSPBrushSides = GetLumpElements( (bspHeader_t*) header, LUMP_BRUSHSIDES, sizeof( *in ) );
101 in = GetLump( (bspHeader_t*) header, LUMP_BRUSHSIDES );
103 for( i = 0; i < numBSPBrushSides; i++ )
105 out->planeNum = in->planeNum;
106 out->shaderNum = in->shaderNum;
107 out->surfaceNum = -1;
114 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 )
175 ibspDrawSurface_t *in;
176 bspDrawSurface_t *out;
180 numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( *in ) );
181 SetDrawSurfaces( numBSPDrawSurfaces );
184 in = GetLump( (bspHeader_t*) header, LUMP_SURFACES );
185 out = bspDrawSurfaces;
186 for( i = 0; i < numBSPDrawSurfaces; i++ )
188 out->shaderNum = in->shaderNum;
189 out->fogNum = in->fogNum;
190 out->surfaceType = in->surfaceType;
191 out->firstVert = in->firstVert;
192 out->numVerts = in->numVerts;
193 out->firstIndex = in->firstIndex;
194 out->numIndexes = in->numIndexes;
196 out->lightmapStyles[ 0 ] = LS_NORMAL;
197 out->vertexStyles[ 0 ] = LS_NORMAL;
198 out->lightmapNum[ 0 ] = in->lightmapNum;
199 out->lightmapX[ 0 ] = in->lightmapX;
200 out->lightmapY[ 0 ] = in->lightmapY;
202 for( j = 1; j < MAX_LIGHTMAPS; j++ )
204 out->lightmapStyles[ j ] = LS_NONE;
205 out->vertexStyles[ j ] = LS_NONE;
206 out->lightmapNum[ j ] = -3;
207 out->lightmapX[ j ] = 0;
208 out->lightmapY[ j ] = 0;
211 out->lightmapWidth = in->lightmapWidth;
212 out->lightmapHeight = in->lightmapHeight;
214 VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
215 VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
216 VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
217 VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
219 out->patchWidth = in->patchWidth;
220 out->patchHeight = in->patchHeight;
228 static void AddDrawSurfacesLump( FILE *file, ibspHeader_t *header )
231 bspDrawSurface_t *in;
232 ibspDrawSurface_t *buffer, *out;
235 /* allocate output buffer */
236 size = numBSPDrawSurfaces * sizeof( *buffer );
237 buffer = safe_malloc( size );
238 memset( buffer, 0, size );
241 in = bspDrawSurfaces;
243 for( i = 0; i < numBSPDrawSurfaces; i++ )
245 out->shaderNum = in->shaderNum;
246 out->fogNum = in->fogNum;
247 out->surfaceType = in->surfaceType;
248 out->firstVert = in->firstVert;
249 out->numVerts = in->numVerts;
250 out->firstIndex = in->firstIndex;
251 out->numIndexes = in->numIndexes;
253 out->lightmapNum = in->lightmapNum[ 0 ];
254 out->lightmapX = in->lightmapX[ 0 ];
255 out->lightmapY = in->lightmapY[ 0 ];
256 out->lightmapWidth = in->lightmapWidth;
257 out->lightmapHeight = in->lightmapHeight;
259 VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
260 VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
261 VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
262 VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
264 out->patchWidth = in->patchWidth;
265 out->patchHeight = in->patchHeight;
272 AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, buffer, size );
292 static void CopyDrawVertsLump( ibspHeader_t *header )
300 numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( *in ) );
301 SetDrawVerts( numBSPDrawVerts );
304 in = GetLump( (bspHeader_t*) header, LUMP_DRAWVERTS );
306 for( i = 0; i < numBSPDrawVerts; i++ )
308 VectorCopy( in->xyz, out->xyz );
309 out->st[ 0 ] = in->st[ 0 ];
310 out->st[ 1 ] = in->st[ 1 ];
312 out->lightmap[ 0 ][ 0 ] = in->lightmap[ 0 ];
313 out->lightmap[ 0 ][ 1 ] = in->lightmap[ 1 ];
315 VectorCopy( in->normal, out->normal );
317 out->color[ 0 ][ 0 ] = in->color[ 0 ];
318 out->color[ 0 ][ 1 ] = in->color[ 1 ];
319 out->color[ 0 ][ 2 ] = in->color[ 2 ];
320 out->color[ 0 ][ 3 ] = in->color[ 3 ];
328 static void AddDrawVertsLump( FILE *file, ibspHeader_t *header )
332 ibspDrawVert_t *buffer, *out;
335 /* allocate output buffer */
336 size = numBSPDrawVerts * sizeof( *buffer );
337 buffer = safe_malloc( size );
338 memset( buffer, 0, size );
343 for( i = 0; i < numBSPDrawVerts; i++ )
345 VectorCopy( in->xyz, out->xyz );
346 out->st[ 0 ] = in->st[ 0 ];
347 out->st[ 1 ] = in->st[ 1 ];
349 out->lightmap[ 0 ] = in->lightmap[ 0 ][ 0 ];
350 out->lightmap[ 1 ] = in->lightmap[ 0 ][ 1 ];
352 VectorCopy( in->normal, out->normal );
354 out->color[ 0 ] = in->color[ 0 ][ 0 ];
355 out->color[ 1 ] = in->color[ 0 ][ 1 ];
356 out->color[ 2 ] = in->color[ 0 ][ 2 ];
357 out->color[ 3 ] = in->color[ 0 ][ 3 ];
364 AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, buffer, size );
382 static void CopyLightGridLumps( ibspHeader_t *header )
390 numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTGRID, sizeof( *in ) );
392 /* allocate buffer */
393 bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
394 memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
397 in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
399 for( i = 0; i < numBSPGridPoints; i++ )
401 for( j = 0; j < MAX_LIGHTMAPS; j++ )
403 VectorCopy( in->ambient, out->ambient[ j ] );
404 VectorCopy( in->directed, out->directed[ j ] );
405 out->styles[ j ] = LS_NONE;
408 out->styles[ 0 ] = LS_NORMAL;
410 out->latLong[ 0 ] = in->latLong[ 0 ];
411 out->latLong[ 1 ] = in->latLong[ 1 ];
419 static void AddLightGridLumps( FILE *file, ibspHeader_t *header )
423 ibspGridPoint_t *buffer, *out;
427 if( bspGridPoints == NULL )
430 /* allocate temporary buffer */
431 buffer = safe_malloc( numBSPGridPoints * sizeof( *out ) );
436 for( i = 0; i < numBSPGridPoints; i++ )
438 VectorCopy( in->ambient[ 0 ], out->ambient );
439 VectorCopy( in->directed[ 0 ], out->directed );
441 out->latLong[ 0 ] = in->latLong[ 0 ];
442 out->latLong[ 1 ] = in->latLong[ 1 ];
449 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, buffer, (numBSPGridPoints * sizeof( *out )) );
451 /* 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( (bspHeader_t*) header, LUMP_SHADERS, bspShaders, sizeof( bspShader_t ) );
482 numBSPModels = CopyLump( (bspHeader_t*) header, LUMP_MODELS, bspModels, sizeof( bspModel_t ) );
484 numBSPPlanes = CopyLump( (bspHeader_t*) header, LUMP_PLANES, bspPlanes, sizeof( bspPlane_t ) );
486 numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) );
488 numBSPNodes = CopyLump( (bspHeader_t*) header, LUMP_NODES, bspNodes, sizeof( bspNode_t ) );
490 numBSPLeafSurfaces = CopyLump( (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ) );
492 numBSPLeafBrushes = CopyLump( (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ) );
494 numBSPBrushes = CopyLump( (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, sizeof( bspBrush_t ) );
496 CopyBrushSidesLump( header );
498 CopyDrawVertsLump( header );
500 CopyDrawSurfacesLump( header );
502 numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFog_t ) );
504 numBSPDrawIndexes = CopyLump( (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ) );
506 numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 );
508 numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 );
509 bspLightBytes = safe_malloc( numBSPLightBytes );
510 CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
512 bspEntDataSize = CopyLump( (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, 1);
514 CopyLightGridLumps( header );
516 /* free the file buffer */
524 writes an id bsp file
527 void WriteIBSPFile( const char *filename )
529 ibspHeader_t outheader, *header;
538 memset( header, 0, sizeof( *header ) );
543 *((int*) (bspHeader_t*) header->ident) = *((int*) game->bspIdent);
544 header->version = LittleLong( game->bspVersion );
546 /* write initial header */
547 file = SafeOpenWrite( filename );
548 SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) ); /* overwritten later */
550 /* add marker lump */
552 sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
553 AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
556 AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
557 AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
558 AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
559 AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
560 AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes*sizeof( bspBrush_t ) );
561 AddBrushSidesLump( file, header );
562 AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
563 AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
564 AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
565 AddDrawVertsLump( file, header );
566 AddDrawSurfacesLump( file, header );
567 AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
568 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
569 AddLightGridLumps( file, header );
570 AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
571 AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
572 AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
575 size = ftell( file );
576 Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / (1024 * 1024), size );
578 /* write the completed header */
579 fseek( file, 0, SEEK_SET );
580 SafeWrite( file, header, sizeof( *header ) );