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