]> git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake3/q3map2/bspfile_rbsp.c
q3map2: switch back to fastallocate option name to reduce diff with NRC, keep compati...
[xonotic/netradiant.git] / tools / quake3 / q3map2 / bspfile_rbsp.c
1 /* -------------------------------------------------------------------------------
2
3    Copyright (C) 1999-2007 id Software, Inc. and contributors.
4    For a list of contributors, see the accompanying CONTRIBUTORS file.
5
6    This file is part of GtkRadiant.
7
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.
12
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.
17
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
21
22    ----------------------------------------------------------------------------------
23
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."
26
27    ------------------------------------------------------------------------------- */
28
29
30
31 /* marker */
32 #define BSPFILE_RBSP_C
33
34
35
36 /* dependencies */
37 #include "q3map2.h"
38
39
40
41
42 /* -------------------------------------------------------------------------------
43
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.
46
47    ------------------------------------------------------------------------------- */
48
49 /* constants */
50 #define LUMP_ENTITIES       0
51 #define LUMP_SHADERS        1
52 #define LUMP_PLANES         2
53 #define LUMP_NODES          3
54 #define LUMP_LEAFS          4
55 #define LUMP_LEAFSURFACES   5
56 #define LUMP_LEAFBRUSHES    6
57 #define LUMP_MODELS         7
58 #define LUMP_BRUSHES        8
59 #define LUMP_BRUSHSIDES     9
60 #define LUMP_DRAWVERTS      10
61 #define LUMP_DRAWINDEXES    11
62 #define LUMP_FOGS           12
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
69
70
71 /* types */
72 typedef struct
73 {
74         char ident[ 4 ];
75         int version;
76
77         bspLump_t lumps[ HEADER_LUMPS ];
78 }
79 rbspHeader_t;
80
81
82
83 /* light grid */
84 #define MAX_MAP_GRID        0xffff
85 #define MAX_MAP_GRIDARRAY   0x100000
86 #define LG_EPSILON          4
87
88
89 static void CopyLightGridLumps( rbspHeader_t *header ){
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_malloc0( numBSPGridPoints * sizeof( *bspGridPoints ) );
100
101         /* copy */
102         inArray = GetLump( (bspHeader_t*) header, LUMP_LIGHTARRAY );
103         in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
104         out = bspGridPoints;
105         for ( i = 0; i < numBSPGridPoints; i++ )
106         {
107                 memcpy( out, &in[ *inArray ], sizeof( *in ) );
108                 inArray++;
109                 out++;
110         }
111 }
112
113
114 static void AddLightGridLumps( FILE *file, rbspHeader_t *header ){
115         int i, j, k, c, d;
116         int numGridPoints, maxGridPoints;
117         bspGridPoint_t  *gridPoints, *in, *out;
118         int numGridArray;
119         unsigned short  *gridArray;
120         qboolean bad;
121
122
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 ) );
127
128         /* zero out */
129         numGridPoints = 0;
130         numGridArray = numBSPGridPoints;
131
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++ )
135         {
136                 /* get points */
137                 in = &bspGridPoints[ i ];
138
139                 /* walk existing list */
140                 for ( j = 0; j < numGridPoints; j++ )
141                 {
142                         /* get point */
143                         out = &gridPoints[ j ];
144
145                         /* compare styles */
146                         if ( memcmp( in->styles, out->styles, MAX_LIGHTMAPS ) ) {
147                                 continue;
148                         }
149
150                         /* compare direction */
151                         d = abs( in->latLong[ 0 ] - out->latLong[ 0 ] );
152                         if ( d < ( 255 - LG_EPSILON ) && d > LG_EPSILON ) {
153                                 continue;
154                         }
155                         d = abs( in->latLong[ 1 ] - out->latLong[ 1 ] );
156                         if ( d < 255 - LG_EPSILON && d > LG_EPSILON ) {
157                                 continue;
158                         }
159
160                         /* compare light */
161                         bad = qfalse;
162                         for ( k = 0; ( k < MAX_LIGHTMAPS && bad == qfalse ); k++ )
163                         {
164                                 for ( c = 0; c < 3; c++ )
165                                 {
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 ) {
168                                                 bad = qtrue;
169                                                 break;
170                                         }
171                                 }
172                         }
173
174                         /* failure */
175                         if ( bad ) {
176                                 continue;
177                         }
178
179                         /* this sample is ok */
180                         break;
181                 }
182
183                 /* set sample index */
184                 gridArray[ i ] = (unsigned short) j;
185
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 ) );
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         rbspHeader_t    *header;
215
216
217         /* load the file header */
218         LoadFile( filename, (void**) &header );
219
220         /* swap the header (except the first 4 bytes) */
221         SwapBlock( (int*) ( (byte*) header + sizeof( int ) ), sizeof( *header ) - sizeof( int ) );
222
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 );
226         }
227         if ( force == qfalse && header->version != game->bspVersion ) {
228                 Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
229         }
230
231         /* load/convert lumps */
232         numBSPShaders = CopyLump_Allocate( (bspHeader_t*) header, LUMP_SHADERS, (void **) &bspShaders, sizeof( bspShader_t ), &allocatedBSPShaders );
233
234         numBSPModels = CopyLump_Allocate( (bspHeader_t*) header, LUMP_MODELS, (void **) &bspModels, sizeof( bspModel_t ), &allocatedBSPModels );
235
236         numBSPPlanes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_PLANES, (void **) &bspPlanes, sizeof( bspPlane_t ), &allocatedBSPPlanes );
237
238         numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) );
239
240         numBSPNodes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_NODES, (void **) &bspNodes, sizeof( bspNode_t ), &allocatedBSPNodes );
241
242         numBSPLeafSurfaces = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFSURFACES, (void **) &bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ), &allocatedBSPLeafSurfaces );
243
244         numBSPLeafBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFBRUSHES, (void **) &bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ), &allocatedBSPLeafBrushes );
245
246         numBSPBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_BRUSHES, (void **) &bspBrushes, sizeof( bspBrush_t ), &allocatedBSPLeafBrushes );
247
248         numBSPBrushSides = CopyLump_Allocate( (bspHeader_t*) header, LUMP_BRUSHSIDES, (void **) &bspBrushSides, sizeof( bspBrushSide_t ), &allocatedBSPBrushSides );
249
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 ] ) );
253
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 ] ) );
257
258         numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFogs[ 0 ] ) );
259
260         numBSPDrawIndexes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_DRAWINDEXES, (void **) &bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ), &allocatedBSPDrawIndexes );
261
262         numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 );
263
264         numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 );
265         bspLightBytes = safe_malloc( numBSPLightBytes );
266         CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
267
268         bspEntDataSize = CopyLump_Allocate( (bspHeader_t*) header, LUMP_ENTITIES, (void **) &bspEntData, 1, &allocatedBSPEntData );
269
270         CopyLightGridLumps( header );
271
272         /* free the file buffer */
273         free( header );
274 }
275
276
277
278 /*
279    WriteRBSPFile()
280    writes a raven bsp file
281  */
282
283 void WriteRBSPFile( const char *filename ){
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 }