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
CopyBrushSidesLump(ibspHeader_t * header)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
AddBrushSidesLump(FILE * file,ibspHeader_t * header)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
CopyDrawSurfacesLump(ibspHeader_t * header)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
AddDrawSurfacesLump(FILE * file,ibspHeader_t * header)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
CopyDrawVertsLump(ibspHeader_t * header)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
AddDrawVertsLump(FILE * file,ibspHeader_t * header)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
CopyLightGridLumps(ibspHeader_t * header)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
AddLightGridLumps(FILE * file,ibspHeader_t * header)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
LoadIBSPFile(const char * filename)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
WriteIBSPFile(const char * filename)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 }
586