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_RBSP_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_LIGHTARRAY 17
68 #define HEADER_LUMPS 18
77 bspLump_t lumps[ HEADER_LUMPS ];
84 #define MAX_MAP_GRID 0xffff
85 #define MAX_MAP_GRIDARRAY 0x100000
89 static void CopyLightGridLumps( rbspHeader_t *header ){
91 unsigned short *inArray;
92 bspGridPoint_t *in, *out;
96 numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTARRAY, sizeof( *inArray ) );
99 bspGridPoints = safe_malloc0( numBSPGridPoints * sizeof( *bspGridPoints ) );
102 inArray = GetLump( (bspHeader_t*) header, LUMP_LIGHTARRAY );
103 in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
105 for ( i = 0; i < numBSPGridPoints; i++ )
107 memcpy( out, &in[ *inArray ], sizeof( *in ) );
114 static void AddLightGridLumps( FILE *file, rbspHeader_t *header ){
116 int numGridPoints, maxGridPoints;
117 bspGridPoint_t *gridPoints, *in, *out;
119 unsigned short *gridArray;
123 /* allocate temporary buffers */
124 maxGridPoints = ( numBSPGridPoints < MAX_MAP_GRID ) ? numBSPGridPoints : MAX_MAP_GRID;
125 gridPoints = safe_malloc( maxGridPoints * sizeof( *gridPoints ) );
126 gridArray = safe_malloc( numBSPGridPoints * sizeof( *gridArray ) );
130 numGridArray = numBSPGridPoints;
132 /* for each bsp grid point, find an approximate twin */
133 Sys_Printf( "Storing lightgrid: %d points\n", numBSPGridPoints );
134 for ( i = 0; i < numGridArray; i++ )
137 in = &bspGridPoints[ i ];
139 /* walk existing list */
140 for ( j = 0; j < numGridPoints; j++ )
143 out = &gridPoints[ j ];
146 if ( memcmp( in->styles, out->styles, MAX_LIGHTMAPS ) ) {
150 /* compare direction */
151 d = abs( in->latLong[ 0 ] - out->latLong[ 0 ] );
152 if ( d < ( 255 - LG_EPSILON ) && d > LG_EPSILON ) {
155 d = abs( in->latLong[ 1 ] - out->latLong[ 1 ] );
156 if ( d < 255 - LG_EPSILON && d > LG_EPSILON ) {
162 for ( k = 0; ( k < MAX_LIGHTMAPS && bad == qfalse ); k++ )
164 for ( c = 0; c < 3; c++ )
166 if ( abs( (int) in->ambient[ k ][ c ] - (int) out->ambient[ k ][ c ] ) > LG_EPSILON ||
167 abs( (int) in->directed[ k ][ c ] - (int) out->directed[ k ][ c ] ) > LG_EPSILON ) {
179 /* this sample is ok */
183 /* set sample index */
184 gridArray[ i ] = (unsigned short) j;
186 /* if no sample found, add a new one */
187 if ( j >= numGridPoints && numGridPoints < maxGridPoints ) {
188 out = &gridPoints[ numGridPoints++ ];
189 memcpy( out, in, sizeof( *in ) );
194 for ( i = 0; i < numGridArray; i++ )
195 gridArray[ i ] = LittleShort( gridArray[ i ] );
198 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, gridPoints, ( numGridPoints * sizeof( *gridPoints ) ) );
199 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTARRAY, gridArray, ( numGridArray * sizeof( *gridArray ) ) );
210 loads a raven bsp file into memory
213 void LoadRBSPFile( const char *filename ){
214 rbspHeader_t *header;
217 /* load the file header */
218 LoadFile( filename, (void**) &header );
220 /* swap the header (except the first 4 bytes) */
221 SwapBlock( (int*) ( (byte*) header + sizeof( int ) ), sizeof( *header ) - sizeof( int ) );
223 /* make sure it matches the format we're trying to load */
224 if ( force == qfalse && *( (int*) header->ident ) != *( (int*) game->bspIdent ) ) {
225 Error( "%s is not a %s file", filename, game->bspIdent );
227 if ( force == qfalse && header->version != game->bspVersion ) {
228 Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
231 /* load/convert lumps */
232 numBSPShaders = CopyLump_Allocate( (bspHeader_t*) header, LUMP_SHADERS, (void **) &bspShaders, sizeof( bspShader_t ), &allocatedBSPShaders );
234 numBSPModels = CopyLump_Allocate( (bspHeader_t*) header, LUMP_MODELS, (void **) &bspModels, sizeof( bspModel_t ), &allocatedBSPModels );
236 numBSPPlanes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_PLANES, (void **) &bspPlanes, sizeof( bspPlane_t ), &allocatedBSPPlanes );
238 numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) );
240 numBSPNodes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_NODES, (void **) &bspNodes, sizeof( bspNode_t ), &allocatedBSPNodes );
242 numBSPLeafSurfaces = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFSURFACES, (void **) &bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ), &allocatedBSPLeafSurfaces );
244 numBSPLeafBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFBRUSHES, (void **) &bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ), &allocatedBSPLeafBrushes );
246 numBSPBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_BRUSHES, (void **) &bspBrushes, sizeof( bspBrush_t ), &allocatedBSPLeafBrushes );
248 numBSPBrushSides = CopyLump_Allocate( (bspHeader_t*) header, LUMP_BRUSHSIDES, (void **) &bspBrushSides, sizeof( bspBrushSide_t ), &allocatedBSPBrushSides );
250 numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( bspDrawVerts[ 0 ] ) );
251 SetDrawVerts( numBSPDrawVerts );
252 CopyLump( (bspHeader_t*) header, LUMP_DRAWVERTS, bspDrawVerts, sizeof( bspDrawVerts[ 0 ] ) );
254 numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( bspDrawSurfaces[ 0 ] ) );
255 SetDrawSurfaces( numBSPDrawSurfaces );
256 CopyLump( (bspHeader_t*) header, LUMP_SURFACES, bspDrawSurfaces, sizeof( bspDrawSurfaces[ 0 ] ) );
258 numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFogs[ 0 ] ) );
260 numBSPDrawIndexes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_DRAWINDEXES, (void **) &bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ), &allocatedBSPDrawIndexes );
262 numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 );
264 numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 );
265 bspLightBytes = safe_malloc( numBSPLightBytes );
266 CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
268 bspEntDataSize = CopyLump_Allocate( (bspHeader_t*) header, LUMP_ENTITIES, (void **) &bspEntData, 1, &allocatedBSPEntData );
270 CopyLightGridLumps( header );
272 /* free the file buffer */
280 writes a raven bsp file
283 void WriteRBSPFile( const char *filename ){
284 rbspHeader_t outheader, *header;
293 memset( header, 0, sizeof( *header ) );
298 *( (int*) (bspHeader_t*) header->ident ) = *( (int*) game->bspIdent );
299 header->version = LittleLong( game->bspVersion );
301 /* write initial header */
302 file = SafeOpenWrite( filename );
303 SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) ); /* overwritten later */
305 /* add marker lump */
307 sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
308 AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
311 AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
312 AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
313 AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
314 AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
315 AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes * sizeof( bspBrush_t ) );
316 AddLump( file, (bspHeader_t*) header, LUMP_BRUSHSIDES, bspBrushSides, numBSPBrushSides * sizeof( bspBrushSides[ 0 ] ) );
317 AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
318 AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
319 AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
320 AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, bspDrawVerts, numBSPDrawVerts * sizeof( bspDrawVerts[ 0 ] ) );
321 AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, bspDrawSurfaces, numBSPDrawSurfaces * sizeof( bspDrawSurfaces[ 0 ] ) );
322 AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
323 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
324 AddLightGridLumps( file, header );
325 AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
326 AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
327 AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
330 size = ftell( file );
331 Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / ( 1024 * 1024 ), size );
333 /* write the completed header */
334 fseek( file, 0, SEEK_SET );
335 SafeWrite( file, header, sizeof( *header ) );