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