2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
21 ----------------------------------------------------------------------------------
\r
23 This code has been altered significantly from its original form, to support
\r
24 several games based on the Quake III Arena engine, in the form of "Q3Map2."
\r
26 ------------------------------------------------------------------------------- */
\r
31 #define BSPFILE_RBSP_C
\r
41 /* -------------------------------------------------------------------------------
\r
43 this file handles translating the bsp file format used by quake 3, rtcw, and ef
\r
44 into the abstracted bsp file used by q3map2.
\r
46 ------------------------------------------------------------------------------- */
\r
49 #define LUMP_ENTITIES 0
\r
50 #define LUMP_SHADERS 1
\r
51 #define LUMP_PLANES 2
\r
52 #define LUMP_NODES 3
\r
53 #define LUMP_LEAFS 4
\r
54 #define LUMP_LEAFSURFACES 5
\r
55 #define LUMP_LEAFBRUSHES 6
\r
56 #define LUMP_MODELS 7
\r
57 #define LUMP_BRUSHES 8
\r
58 #define LUMP_BRUSHSIDES 9
\r
59 #define LUMP_DRAWVERTS 10
\r
60 #define LUMP_DRAWINDEXES 11
\r
61 #define LUMP_FOGS 12
\r
62 #define LUMP_SURFACES 13
\r
63 #define LUMP_LIGHTMAPS 14
\r
64 #define LUMP_LIGHTGRID 15
\r
65 #define LUMP_VISIBILITY 16
\r
66 #define LUMP_LIGHTARRAY 17
\r
67 #define HEADER_LUMPS 18
\r
76 bspLump_t lumps[ HEADER_LUMPS ];
\r
83 #define MAX_MAP_GRID 0xffff
\r
84 #define MAX_MAP_GRIDARRAY 0x100000
\r
85 #define LG_EPSILON 4
\r
88 static void CopyLightGridLumps( rbspHeader_t *header )
\r
91 unsigned short *inArray;
\r
92 bspGridPoint_t *in, *out;
\r
96 numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTARRAY, sizeof( *inArray ) );
\r
98 /* allocate buffer */
\r
99 bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
\r
100 memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
\r
103 inArray = GetLump( (bspHeader_t*) header, LUMP_LIGHTARRAY );
\r
104 in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
\r
105 out = bspGridPoints;
\r
106 for( i = 0; i < numBSPGridPoints; i++ )
\r
108 memcpy( out, &in[ *inArray ], sizeof( *in ) );
\r
115 static void AddLightGridLumps( FILE *file, rbspHeader_t *header )
\r
118 int numGridPoints, maxGridPoints;
\r
119 bspGridPoint_t *gridPoints, *in, *out;
\r
121 unsigned short *gridArray;
\r
125 /* allocate temporary buffers */
\r
126 maxGridPoints = (numBSPGridPoints < MAX_MAP_GRID) ? numBSPGridPoints : MAX_MAP_GRID;
\r
127 gridPoints = safe_malloc( maxGridPoints * sizeof( *gridPoints ) );
\r
128 gridArray = safe_malloc( numBSPGridPoints * sizeof( *gridArray ) );
\r
132 numGridArray = numBSPGridPoints;
\r
134 /* for each bsp grid point, find an approximate twin */
\r
135 Sys_Printf( "Storing lightgrid: %d points\n", numBSPGridPoints );
\r
136 for( i = 0; i < numGridArray; i++ )
\r
139 in = &bspGridPoints[ i ];
\r
141 /* walk existing list */
\r
142 for( j = 0; j < numGridPoints; j++ )
\r
145 out = &gridPoints[ j ];
\r
147 /* compare styles */
\r
148 if( *((unsigned int*) in->styles) != *((unsigned int*) out->styles) )
\r
151 /* compare direction */
\r
152 d = abs( in->latLong[ 0 ] - out->latLong[ 0 ] );
\r
153 if( d < (255 - LG_EPSILON) && d > LG_EPSILON )
\r
155 d = abs( in->latLong[ 1 ] - out->latLong[ 1 ] );
\r
156 if( d < 255 - LG_EPSILON && d > LG_EPSILON )
\r
159 /* compare light */
\r
161 for( k = 0; (k < MAX_LIGHTMAPS && bad == qfalse); k++ )
\r
163 for( c = 0; c < 3; c++ )
\r
165 if( abs( (int) in->ambient[ k ][ c ] - (int) out->ambient[ k ][ c ]) > LG_EPSILON ||
\r
166 abs( (int) in->directed[ k ][ c ] - (int) out->directed[ k ][ c ]) > LG_EPSILON )
\r
178 /* this sample is ok */
\r
182 /* set sample index */
\r
183 gridArray[ i ] = (unsigned short) j;
\r
185 /* if no sample found, add a new one */
\r
186 if( j >= numGridPoints && numGridPoints < maxGridPoints )
\r
188 out = &gridPoints[ numGridPoints++ ];
\r
189 memcpy( out, in, sizeof( *in ) );
\r
194 for( i = 0; i < numGridArray; i++ )
\r
195 gridArray[ i ] = LittleShort( gridArray[ i ] );
\r
198 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, gridPoints, (numGridPoints * sizeof( *gridPoints )) );
\r
199 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTARRAY, gridArray, (numGridArray * sizeof( *gridArray )) );
\r
202 free( gridPoints );
\r
210 loads a raven bsp file into memory
\r
213 void LoadRBSPFile( const char *filename )
\r
215 rbspHeader_t *header;
\r
218 /* load the file header */
\r
219 LoadFile( filename, (void**) &header );
\r
221 /* swap the header (except the first 4 bytes) */
\r
222 SwapBlock( (int*) ((byte*) header + sizeof( int )), sizeof( *header ) - sizeof( int ) );
\r
224 /* make sure it matches the format we're trying to load */
\r
225 if( force == qfalse && *((int*) header->ident) != *((int*) game->bspIdent) )
\r
226 Error( "%s is not a %s file", filename, game->bspIdent );
\r
227 if( force == qfalse && header->version != game->bspVersion )
\r
228 Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
\r
230 /* load/convert lumps */
\r
231 numBSPShaders = CopyLump( (bspHeader_t*) header, LUMP_SHADERS, bspShaders, sizeof( bspShader_t ) );
\r
233 numBSPModels = CopyLump( (bspHeader_t*) header, LUMP_MODELS, bspModels, sizeof( bspModel_t ) );
\r
235 numBSPPlanes = CopyLump( (bspHeader_t*) header, LUMP_PLANES, bspPlanes, sizeof( bspPlane_t ) );
\r
237 numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) );
\r
239 numBSPNodes = CopyLump( (bspHeader_t*) header, LUMP_NODES, bspNodes, sizeof( bspNode_t ) );
\r
241 numBSPLeafSurfaces = CopyLump( (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ) );
\r
243 numBSPLeafBrushes = CopyLump( (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ) );
\r
245 numBSPBrushes = CopyLump( (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, sizeof( bspBrush_t ) );
\r
247 numBSPBrushSides = CopyLump( (bspHeader_t*) header, LUMP_BRUSHSIDES, bspBrushSides, sizeof( bspBrushSide_t ) );
\r
249 numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( bspDrawVerts[ 0 ] ) );
\r
250 SetDrawVerts( numBSPDrawVerts );
\r
251 CopyLump( (bspHeader_t*) header, LUMP_DRAWVERTS, bspDrawVerts, sizeof( bspDrawVerts[ 0 ] ) );
\r
253 numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( bspDrawSurfaces[ 0 ] ) );
\r
254 SetDrawSurfaces( numBSPDrawSurfaces );
\r
255 CopyLump( (bspHeader_t*) header, LUMP_SURFACES, bspDrawSurfaces, sizeof( bspDrawSurfaces[ 0 ] ) );
\r
257 numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFogs[ 0 ] ) );
\r
259 numBSPDrawIndexes = CopyLump( (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ) );
\r
261 numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 );
\r
263 numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 );
\r
264 bspLightBytes = safe_malloc( numBSPLightBytes );
\r
265 CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
\r
267 bspEntDataSize = CopyLump( (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, 1);
\r
269 CopyLightGridLumps( header );
\r
271 /* free the file buffer */
\r
279 writes a raven bsp file
\r
282 void WriteRBSPFile( const char *filename )
\r
284 rbspHeader_t outheader, *header;
\r
287 char marker[ 1024 ];
\r
292 header = &outheader;
\r
293 memset( header, 0, sizeof( *header ) );
\r
297 /* set up header */
\r
298 *((int*) (bspHeader_t*) header->ident) = *((int*) game->bspIdent);
\r
299 header->version = LittleLong( game->bspVersion );
\r
301 /* write initial header */
\r
302 file = SafeOpenWrite( filename );
\r
303 SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) ); /* overwritten later */
\r
305 /* add marker lump */
\r
307 sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
\r
308 AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
\r
311 AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
\r
312 AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
\r
313 AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
\r
314 AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
\r
315 AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes*sizeof( bspBrush_t ) );
\r
316 AddLump( file, (bspHeader_t*) header, LUMP_BRUSHSIDES, bspBrushSides, numBSPBrushSides * sizeof( bspBrushSides[ 0 ] ) );
\r
317 AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
\r
318 AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
\r
319 AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
\r
320 AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, bspDrawVerts, numBSPDrawVerts * sizeof( bspDrawVerts[ 0 ] ) );
\r
321 AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, bspDrawSurfaces, numBSPDrawSurfaces * sizeof( bspDrawSurfaces[ 0 ] ) );
\r
322 AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
\r
323 AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
\r
324 AddLightGridLumps( file, header );
\r
325 AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
\r
326 AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
\r
327 AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
\r
329 /* emit bsp size */
\r
330 size = ftell( file );
\r
331 Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / (1024 * 1024), size );
\r
333 /* write the completed header */
\r
334 fseek( file, 0, SEEK_SET );
\r
335 SafeWrite( file, header, sizeof( *header ) );
\r
337 /* close the file */
\r