Author: rambetter
[divverent/netradiant.git] / tools / quake3 / q3map2 / bspfile_ibsp.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_IBSP_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_ADVERTISEMENTS 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 ibspHeader_t;
80
81
82
83 /* brush sides */
84 typedef struct
85 {
86         int                     planeNum;
87         int                     shaderNum;
88 }
89 ibspBrushSide_t;
90
91
92 static void CopyBrushSidesLump( ibspHeader_t *header )
93 {
94         int                             i;
95         ibspBrushSide_t *in;
96         bspBrushSide_t  *out;
97         
98         
99         /* get count */
100         numBSPBrushSides = GetLumpElements( (bspHeader_t*) header, LUMP_BRUSHSIDES, sizeof( *in ) );
101         
102         /* copy */
103         in = GetLump( (bspHeader_t*) header, LUMP_BRUSHSIDES );
104         for( i = 0; i < numBSPBrushSides; i++ )
105         {
106                 AUTOEXPAND_BY_REALLOC(bspBrushSides, i, allocatedBSPBrushSides, 1024);
107                 out = &bspBrushSides[i];
108                 out->planeNum = in->planeNum;
109                 out->shaderNum = in->shaderNum;
110                 out->surfaceNum = -1;
111                 in++;
112         }
113 }
114
115
116 static void AddBrushSidesLump( FILE *file, ibspHeader_t *header )
117 {
118         int                             i, size;
119         bspBrushSide_t  *in;
120         ibspBrushSide_t *buffer, *out;
121         
122         
123         /* allocate output buffer */
124         size = numBSPBrushSides * sizeof( *buffer );
125         buffer = safe_malloc( size );
126         memset( buffer, 0, size );
127         
128         /* convert */
129         in = bspBrushSides;
130         out = buffer;
131         for( i = 0; i < numBSPBrushSides; i++ )
132         {
133                 out->planeNum = in->planeNum;
134                 out->shaderNum = in->shaderNum;
135                 in++;
136                 out++;
137         }
138         
139         /* write lump */
140         AddLump( file, (bspHeader_t*) header, LUMP_BRUSHSIDES, buffer, size );
141         
142         /* free buffer */
143         free( buffer );
144 }
145
146
147
148 /* drawsurfaces */
149 typedef struct ibspDrawSurface_s
150 {
151         int                     shaderNum;
152         int                     fogNum;
153         int                     surfaceType;
154         
155         int                     firstVert;
156         int                     numVerts;
157         
158         int                     firstIndex;
159         int                     numIndexes;
160         
161         int                     lightmapNum;
162         int                     lightmapX, lightmapY;
163         int                     lightmapWidth, lightmapHeight;
164         
165         vec3_t          lightmapOrigin;
166         vec3_t          lightmapVecs[ 3 ];
167         
168         int                     patchWidth;
169         int                     patchHeight;
170 }
171 ibspDrawSurface_t;
172
173
174 static void CopyDrawSurfacesLump( ibspHeader_t *header )
175 {
176         int                                     i, j;
177         ibspDrawSurface_t       *in;
178         bspDrawSurface_t        *out;
179         
180         
181         /* get count */
182         numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( *in ) );
183         SetDrawSurfaces( numBSPDrawSurfaces );
184         
185         /* copy */
186         in = GetLump( (bspHeader_t*) header, LUMP_SURFACES );
187         out = bspDrawSurfaces;
188         for( i = 0; i < numBSPDrawSurfaces; i++ )
189         {
190                 out->shaderNum = in->shaderNum;
191                 out->fogNum = in->fogNum;
192                 out->surfaceType = in->surfaceType;
193                 out->firstVert = in->firstVert;
194                 out->numVerts = in->numVerts;
195                 out->firstIndex = in->firstIndex;
196                 out->numIndexes = in->numIndexes;
197                 
198                 out->lightmapStyles[ 0 ] = LS_NORMAL;
199                 out->vertexStyles[ 0 ] = LS_NORMAL;
200                 out->lightmapNum[ 0 ] = in->lightmapNum;
201                 out->lightmapX[ 0 ] = in->lightmapX;
202                 out->lightmapY[ 0 ] = in->lightmapY;
203                 
204                 for( j = 1; j < MAX_LIGHTMAPS; j++ )
205                 {
206                         out->lightmapStyles[ j ] = LS_NONE;
207                         out->vertexStyles[ j ] = LS_NONE;
208                         out->lightmapNum[ j ] = -3;
209                         out->lightmapX[ j ] = 0;
210                         out->lightmapY[ j ] = 0;
211                 }
212                 
213                 out->lightmapWidth = in->lightmapWidth;
214                 out->lightmapHeight = in->lightmapHeight;
215                 
216                 VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
217                 VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
218                 VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
219                 VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
220                 
221                 out->patchWidth = in->patchWidth;
222                 out->patchHeight = in->patchHeight;
223                 
224                 in++;
225                 out++;
226         }
227 }
228
229
230 static void AddDrawSurfacesLump( FILE *file, ibspHeader_t *header )
231 {
232         int                                     i, size;
233         bspDrawSurface_t        *in;
234         ibspDrawSurface_t       *buffer, *out;
235         
236         
237         /* allocate output buffer */
238         size = numBSPDrawSurfaces * sizeof( *buffer );
239         buffer = safe_malloc( size );
240         memset( buffer, 0, size );
241         
242         /* convert */
243         in = bspDrawSurfaces;
244         out = buffer;
245         for( i = 0; i < numBSPDrawSurfaces; i++ )
246         {
247                 out->shaderNum = in->shaderNum;
248                 out->fogNum = in->fogNum;
249                 out->surfaceType = in->surfaceType;
250                 out->firstVert = in->firstVert;
251                 out->numVerts = in->numVerts;
252                 out->firstIndex = in->firstIndex;
253                 out->numIndexes = in->numIndexes;
254                 
255                 out->lightmapNum = in->lightmapNum[ 0 ];
256                 out->lightmapX = in->lightmapX[ 0 ];
257                 out->lightmapY = in->lightmapY[ 0 ];
258                 out->lightmapWidth = in->lightmapWidth;
259                 out->lightmapHeight = in->lightmapHeight;
260                 
261                 VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
262                 VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
263                 VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
264                 VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
265                 
266                 out->patchWidth = in->patchWidth;
267                 out->patchHeight = in->patchHeight;
268                 
269                 in++;
270                 out++;
271         }
272         
273         /* write lump */
274         AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, buffer, size );
275         
276         /* free buffer */
277         free( buffer );
278 }
279
280
281
282 /* drawverts */
283 typedef struct
284 {
285         vec3_t          xyz;
286         float           st[ 2 ];
287         float           lightmap[ 2 ];
288         vec3_t          normal;
289         byte            color[ 4 ];
290 }
291 ibspDrawVert_t;
292
293
294 static void CopyDrawVertsLump( ibspHeader_t *header )
295 {
296         int                             i;
297         ibspDrawVert_t  *in;
298         bspDrawVert_t   *out;
299         
300         
301         /* get count */
302         numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( *in ) );
303         SetDrawVerts( numBSPDrawVerts );
304         
305         /* copy */
306         in = GetLump( (bspHeader_t*) header, LUMP_DRAWVERTS );
307         out = bspDrawVerts;
308         for( i = 0; i < numBSPDrawVerts; i++ )
309         {
310                 VectorCopy( in->xyz, out->xyz );
311                 out->st[ 0 ] = in->st[ 0 ];
312                 out->st[ 1 ] = in->st[ 1 ];
313                 
314                 out->lightmap[ 0 ][ 0 ] = in->lightmap[ 0 ];
315                 out->lightmap[ 0 ][ 1 ] = in->lightmap[ 1 ];
316                 
317                 VectorCopy( in->normal, out->normal );
318                 
319                 out->color[ 0 ][ 0 ] = in->color[ 0 ];
320                 out->color[ 0 ][ 1 ] = in->color[ 1 ];
321                 out->color[ 0 ][ 2 ] = in->color[ 2 ];
322                 out->color[ 0 ][ 3 ] = in->color[ 3 ];
323                 
324                 in++;
325                 out++;
326         }
327 }
328
329
330 static void AddDrawVertsLump( FILE *file, ibspHeader_t *header )
331 {
332         int                             i, size;
333         bspDrawVert_t   *in;
334         ibspDrawVert_t  *buffer, *out;
335         
336         
337         /* allocate output buffer */
338         size = numBSPDrawVerts * sizeof( *buffer );
339         buffer = safe_malloc( size );
340         memset( buffer, 0, size );
341         
342         /* convert */
343         in = bspDrawVerts;
344         out = buffer;
345         for( i = 0; i < numBSPDrawVerts; i++ )
346         {
347                 VectorCopy( in->xyz, out->xyz );
348                 out->st[ 0 ] = in->st[ 0 ];
349                 out->st[ 1 ] = in->st[ 1 ];
350                 
351                 out->lightmap[ 0 ] = in->lightmap[ 0 ][ 0 ];
352                 out->lightmap[ 1 ] = in->lightmap[ 0 ][ 1 ];
353                 
354                 VectorCopy( in->normal, out->normal );
355                 
356                 out->color[ 0 ] = in->color[ 0 ][ 0 ];
357                 out->color[ 1 ] = in->color[ 0 ][ 1 ];
358                 out->color[ 2 ] = in->color[ 0 ][ 2 ];
359                 out->color[ 3 ] = in->color[ 0 ][ 3 ];
360                 
361                 in++;
362                 out++;
363         }
364         
365         /* write lump */
366         AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, buffer, size );
367         
368         /* free buffer */
369         free( buffer );
370 }
371
372
373
374 /* light grid */
375 typedef struct
376 {
377         byte            ambient[ 3 ];
378         byte            directed[ 3 ];
379         byte            latLong[ 2 ];
380 }
381 ibspGridPoint_t;
382
383
384 static void CopyLightGridLumps( ibspHeader_t *header )
385 {
386         int                             i, j;
387         ibspGridPoint_t *in;
388         bspGridPoint_t  *out;
389         
390         
391         /* get count */
392         numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTGRID, sizeof( *in ) );
393         
394         /* allocate buffer */
395         bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
396         memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
397         
398         /* copy */
399         in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
400         out = bspGridPoints;
401         for( i = 0; i < numBSPGridPoints; i++ )
402         {
403                 for( j = 0; j < MAX_LIGHTMAPS; j++ )
404                 {
405                         VectorCopy( in->ambient, out->ambient[ j ] );
406                         VectorCopy( in->directed, out->directed[ j ] );
407                         out->styles[ j ] = LS_NONE;
408                 }
409                 
410                 out->styles[ 0 ] = LS_NORMAL;
411                 
412                 out->latLong[ 0 ] = in->latLong[ 0 ];
413                 out->latLong[ 1 ] = in->latLong[ 1 ];
414                 
415                 in++;
416                 out++;
417         }
418 }
419
420
421 static void AddLightGridLumps( FILE *file, ibspHeader_t *header )
422 {
423         int                             i;
424         bspGridPoint_t  *in;
425         ibspGridPoint_t *buffer, *out;
426         
427         
428         /* dummy check */
429         if( bspGridPoints == NULL )
430                 return;
431         
432         /* allocate temporary buffer */
433         buffer = safe_malloc( numBSPGridPoints * sizeof( *out ) );
434         
435         /* convert */
436         in = bspGridPoints;
437         out = buffer;
438         for( i = 0; i < numBSPGridPoints; i++ )
439         {
440                 VectorCopy( in->ambient[ 0 ], out->ambient );
441                 VectorCopy( in->directed[ 0 ], out->directed );
442                 
443                 out->latLong[ 0 ] = in->latLong[ 0 ];
444                 out->latLong[ 1 ] = in->latLong[ 1 ];
445                 
446                 in++;
447                 out++;
448         }
449         
450         /* write lumps */
451         AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, buffer, (numBSPGridPoints * sizeof( *out )) );
452         
453         /* free buffer (ydnar 2002-10-22: [bug 641] thanks Rap70r! */
454         free( buffer );
455 }
456
457 /*
458 LoadIBSPFile()
459 loads a quake 3 bsp file into memory
460 */
461
462 void LoadIBSPFile( const char *filename )
463 {
464         ibspHeader_t    *header;
465         
466         
467         /* load the file header */
468         LoadFile( filename, (void**) &header );
469
470         /* swap the header (except the first 4 bytes) */
471         SwapBlock( (int*) ((byte*) header + sizeof( int )), sizeof( *header ) - sizeof( int ) );
472         
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 );
478         
479         /* load/convert lumps */
480         numBSPShaders = CopyLump_Allocate( (bspHeader_t*) header, LUMP_SHADERS, (void **) &bspShaders, sizeof( bspShader_t ), &allocatedBSPShaders );
481         
482         numBSPModels = CopyLump_Allocate( (bspHeader_t*) header, LUMP_MODELS, (void **) &bspModels, sizeof( bspModel_t ), &allocatedBSPModels );
483         
484         numBSPPlanes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_PLANES, (void **) &bspPlanes, sizeof( bspPlane_t ), &allocatedBSPPlanes );
485         
486         numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) ); // TODO fix overflow
487         
488         numBSPNodes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_NODES, (void **) &bspNodes, sizeof( bspNode_t ), &allocatedBSPNodes );
489         
490         numBSPLeafSurfaces = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFSURFACES, (void **) &bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ), &allocatedBSPLeafSurfaces );
491         
492         numBSPLeafBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_LEAFBRUSHES, (void **) &bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ), &allocatedBSPLeafBrushes );
493         
494         numBSPBrushes = CopyLump_Allocate( (bspHeader_t*) header, LUMP_BRUSHES, (void **) &bspBrushes, sizeof( bspBrush_t ), &allocatedBSPLeafBrushes );
495         
496         CopyBrushSidesLump( header );
497
498         CopyDrawVertsLump( header );
499         
500         CopyDrawSurfacesLump( header );
501         
502         numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFog_t ) ); // TODO fix overflow
503         
504         numBSPDrawIndexes = CopyLump( (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ) );
505         
506         numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 ); // TODO fix overflow
507         
508         numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 ); // TODO change to CopyLump_Allocate
509                 bspLightBytes = safe_malloc( numBSPLightBytes );
510                 CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
511         
512         bspEntDataSize = CopyLump_Allocate( (bspHeader_t*) header, LUMP_ENTITIES, (void **) &bspEntData, 1, &allocatedBSPEntData);
513         
514         CopyLightGridLumps( header );
515
516         /* advertisements */
517         if(header->version == 47) // quake live's bsp version
518                 numBSPAds = CopyLump( (bspHeader_t*) header, LUMP_ADVERTISEMENTS, bspAds, sizeof( bspAdvertisement_t ) );
519         else
520                 numBSPAds = 0;
521
522         /* free the file buffer */
523         free( header );
524 }
525
526
527
528 /*
529 WriteIBSPFile()
530 writes an id bsp file
531 */
532
533 void WriteIBSPFile( const char *filename )
534 {               
535         ibspHeader_t    outheader, *header;
536         FILE                    *file;
537         time_t                  t;
538         char                    marker[ 1024 ];
539         int                             size;
540         
541         
542         /* set header */
543         header = &outheader;
544         memset( header, 0, sizeof( *header ) );
545         
546         //%     Swapfile();
547         
548         /* set up header */
549         *((int*) (bspHeader_t*) header->ident) = *((int*) game->bspIdent);
550         header->version = LittleLong( game->bspVersion );
551         
552         /* write initial header */
553         file = SafeOpenWrite( filename );
554         SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) );    /* overwritten later */
555         
556         /* add marker lump */
557         time( &t );
558         sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
559         AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
560         
561         /* add lumps */
562         AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
563         AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
564         AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
565         AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
566         AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes*sizeof( bspBrush_t ) );
567         AddBrushSidesLump( file, header );
568         AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
569         AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
570         AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
571         AddDrawVertsLump( file, header );
572         AddDrawSurfacesLump( file, header );
573         AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
574         AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
575         AddLightGridLumps( file, header );
576         AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
577         AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
578         AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
579
580         /* advertisements */
581         AddLump( file, (bspHeader_t*) header, LUMP_ADVERTISEMENTS, bspAds, numBSPAds * sizeof( bspAdvertisement_t ) );
582
583         /* emit bsp size */
584         size = ftell( file );
585         Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / (1024 * 1024), size );
586         
587         /* write the completed header */
588         fseek( file, 0, SEEK_SET );
589         SafeWrite( file, header, sizeof( *header ) );
590         
591         /* close the file */
592         fclose( file ); 
593 }