]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/bspfile_rbsp.c
* moved zeroradiant (1.6) into trunk
[xonotic/netradiant.git] / tools / quake3 / q3map2 / bspfile_rbsp.c
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
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.
11
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.
16
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
20
21 ----------------------------------------------------------------------------------
22
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."
25
26 ------------------------------------------------------------------------------- */
27
28
29
30 /* marker */
31 #define BSPFILE_RBSP_C
32
33
34
35 /* dependencies */
36 #include "q3map2.h"
37
38
39
40
41 /* -------------------------------------------------------------------------------
42
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.
45
46 ------------------------------------------------------------------------------- */
47
48 /* constants */
49 #define LUMP_ENTITIES           0
50 #define LUMP_SHADERS            1
51 #define LUMP_PLANES                     2
52 #define LUMP_NODES                      3
53 #define LUMP_LEAFS                      4
54 #define LUMP_LEAFSURFACES       5
55 #define LUMP_LEAFBRUSHES        6
56 #define LUMP_MODELS                     7
57 #define LUMP_BRUSHES            8
58 #define LUMP_BRUSHSIDES         9
59 #define LUMP_DRAWVERTS          10
60 #define LUMP_DRAWINDEXES        11
61 #define LUMP_FOGS                       12
62 #define LUMP_SURFACES           13
63 #define LUMP_LIGHTMAPS          14
64 #define LUMP_LIGHTGRID          15
65 #define LUMP_VISIBILITY         16
66 #define LUMP_LIGHTARRAY         17
67 #define HEADER_LUMPS            18
68
69
70 /* types */
71 typedef struct
72 {
73         char            ident[ 4 ];
74         int                     version;
75         
76         bspLump_t       lumps[ HEADER_LUMPS ];
77 }
78 rbspHeader_t;
79
80
81
82 /* light grid */
83 #define MAX_MAP_GRID            0xffff
84 #define MAX_MAP_GRIDARRAY       0x100000
85 #define LG_EPSILON                      4
86
87
88 static void CopyLightGridLumps( rbspHeader_t *header )
89 {
90         int                             i;
91         unsigned short  *inArray;
92         bspGridPoint_t  *in, *out;
93         
94         
95         /* get count */
96         numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTARRAY, sizeof( *inArray ) );
97         
98         /* allocate buffer */
99         bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
100         memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
101         
102         /* copy */
103         inArray = GetLump( (bspHeader_t*) header, LUMP_LIGHTARRAY );
104         in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
105         out = bspGridPoints;
106         for( i = 0; i < numBSPGridPoints; i++ )
107         {
108                 memcpy( out, &in[ *inArray ], sizeof( *in ) );
109                 inArray++;
110                 out++;
111         }
112 }
113
114
115 static void AddLightGridLumps( FILE *file, rbspHeader_t *header )
116 {
117         int                             i, j, k, c, d;
118         int                             numGridPoints, maxGridPoints;
119         bspGridPoint_t  *gridPoints, *in, *out;
120         int                             numGridArray;
121         unsigned short  *gridArray;
122         qboolean                bad;
123         
124         
125         /* allocate temporary buffers */
126         maxGridPoints = (numBSPGridPoints < MAX_MAP_GRID) ? numBSPGridPoints : MAX_MAP_GRID;
127         gridPoints = safe_malloc( maxGridPoints * sizeof( *gridPoints ) );
128         gridArray = safe_malloc( numBSPGridPoints * sizeof( *gridArray ) );
129         
130         /* zero out */
131         numGridPoints = 0;
132         numGridArray = numBSPGridPoints;
133         
134         /* for each bsp grid point, find an approximate twin */
135         Sys_Printf( "Storing lightgrid: %d points\n", numBSPGridPoints );
136         for( i = 0; i < numGridArray; i++ )
137         {
138                 /* get points */
139                 in = &bspGridPoints[ i ];
140                 
141                 /* walk existing list */
142                 for( j = 0; j < numGridPoints; j++ )
143                 {
144                         /* get point */
145                         out = &gridPoints[ j ];
146                         
147                         /* compare styles */
148                         if( *((unsigned int*) in->styles) != *((unsigned int*) out->styles) )
149                                 continue;
150                         
151                         /* compare direction */
152                         d = abs( in->latLong[ 0 ] - out->latLong[ 0 ] );
153                         if( d < (255 - LG_EPSILON) && d > LG_EPSILON )
154                                 continue;
155                         d = abs( in->latLong[ 1 ] - out->latLong[ 1 ] );
156                         if( d < 255 - LG_EPSILON && d > LG_EPSILON )
157                                 continue;
158                         
159                         /* compare light */
160                         bad = qfalse;
161                         for( k = 0; (k < MAX_LIGHTMAPS && bad == qfalse); k++ )
162                         {
163                                 for( c = 0; c < 3; c++ )
164                                 {
165                                         if( abs( (int) in->ambient[ k ][ c ] - (int) out->ambient[ k ][ c ]) > LG_EPSILON ||
166                                                 abs( (int) in->directed[ k ][ c ] - (int) out->directed[ k ][ c ]) > LG_EPSILON )
167                                         {
168                                                 bad = qtrue;
169                                                 break;
170                                         }
171                                 }
172                         }
173                         
174                         /* failure */
175                         if( bad )
176                                 continue;
177                         
178                         /* this sample is ok */
179                         break;
180                 }
181                 
182                 /* set sample index */
183                 gridArray[ i ] = (unsigned short) j;
184                 
185                 /* if no sample found, add a new one */
186                 if( j >= numGridPoints && numGridPoints < maxGridPoints )
187                 {
188                         out = &gridPoints[ numGridPoints++ ];
189                         memcpy( out, in, sizeof( *in ) );
190                 }
191         }
192         
193         /* swap array */
194         for( i = 0; i < numGridArray; i++ )
195                 gridArray[ i ] = LittleShort( gridArray[ i ] );
196         
197         /* write lumps */
198         AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, gridPoints, (numGridPoints * sizeof( *gridPoints )) );
199         AddLump( file, (bspHeader_t*) header, LUMP_LIGHTARRAY, gridArray, (numGridArray * sizeof( *gridArray )) );
200         
201         /* free buffers */
202         free( gridPoints );
203         free( gridArray );
204 }
205
206
207
208 /*
209 LoadRBSPFile()
210 loads a raven bsp file into memory
211 */
212
213 void LoadRBSPFile( const char *filename )
214 {
215         rbspHeader_t    *header;
216         
217         
218         /* load the file header */
219         LoadFile( filename, (void**) &header );
220
221         /* swap the header (except the first 4 bytes) */
222         SwapBlock( (int*) ((byte*) header + sizeof( int )), sizeof( *header ) - sizeof( int ) );
223         
224         /* make sure it matches the format we're trying to load */
225         if( force == qfalse && *((int*) header->ident) != *((int*) game->bspIdent) )
226                 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 );
229         
230         /* load/convert lumps */
231         numBSPShaders = CopyLump( (bspHeader_t*) header, LUMP_SHADERS, bspShaders, sizeof( bspShader_t ) );
232         
233         numBSPModels = CopyLump( (bspHeader_t*) header, LUMP_MODELS, bspModels, sizeof( bspModel_t ) );
234         
235         numBSPPlanes = CopyLump( (bspHeader_t*) header, LUMP_PLANES, bspPlanes, sizeof( bspPlane_t ) );
236         
237         numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) );
238         
239         numBSPNodes = CopyLump( (bspHeader_t*) header, LUMP_NODES, bspNodes, sizeof( bspNode_t ) );
240         
241         numBSPLeafSurfaces = CopyLump( (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ) );
242         
243         numBSPLeafBrushes = CopyLump( (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ) );
244         
245         numBSPBrushes = CopyLump( (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, sizeof( bspBrush_t ) );
246         
247         numBSPBrushSides = CopyLump( (bspHeader_t*) header, LUMP_BRUSHSIDES, bspBrushSides, sizeof( bspBrushSide_t ) );
248         
249         numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( bspDrawVerts[ 0 ] ) );
250                 SetDrawVerts( numBSPDrawVerts );
251                 CopyLump( (bspHeader_t*) header, LUMP_DRAWVERTS, bspDrawVerts, sizeof( bspDrawVerts[ 0 ] ) );
252         
253         numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( bspDrawSurfaces[ 0 ] ) );
254                 SetDrawSurfaces( numBSPDrawSurfaces );
255                 CopyLump( (bspHeader_t*) header, LUMP_SURFACES, bspDrawSurfaces, sizeof( bspDrawSurfaces[ 0 ] ) );
256         
257         numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFogs[ 0 ] ) );
258         
259         numBSPDrawIndexes = CopyLump( (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ) );
260         
261         numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 );
262         
263         numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 );
264                 bspLightBytes = safe_malloc( numBSPLightBytes );
265                 CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
266         
267         bspEntDataSize = CopyLump( (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, 1);
268         
269         CopyLightGridLumps( header );
270         
271         /* free the file buffer */
272         free( header );
273 }
274
275
276
277 /*
278 WriteRBSPFile()
279 writes a raven bsp file
280 */
281
282 void WriteRBSPFile( const char *filename )
283 {               
284         rbspHeader_t    outheader, *header;
285         FILE                    *file;
286         time_t                  t;
287         char                    marker[ 1024 ];
288         int                             size;
289         
290         
291         /* set header */
292         header = &outheader;
293         memset( header, 0, sizeof( *header ) );
294         
295         //%     Swapfile();
296         
297         /* set up header */
298         *((int*) (bspHeader_t*) header->ident) = *((int*) game->bspIdent);
299         header->version = LittleLong( game->bspVersion );
300         
301         /* write initial header */
302         file = SafeOpenWrite( filename );
303         SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) );    /* overwritten later */
304         
305         /* add marker lump */
306         time( &t );
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 );
309         
310         /* add lumps */
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 ] ) );
328         
329         /* emit bsp size */
330         size = ftell( file );
331         Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / (1024 * 1024), size );
332         
333         /* write the completed header */
334         fseek( file, 0, SEEK_SET );
335         SafeWrite( file, header, sizeof( *header ) );
336         
337         /* close the file */
338         fclose( file ); 
339 }