1 /*
2 Copyright (C) 1999-2006 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 #include "qbsp.h"
22
23 int c_nofaces;
24 int c_facenodes;
25
26
27 /*
28 =========================================================
29
30 ONLY SAVE OUT PLANES THAT ARE ACTUALLY USED AS NODES
31
32 =========================================================
33 */
34
35 int planeused[MAX_MAP_PLANES];
36
37 /*
38 ============
39 EmitPlanes
40
41 There is no oportunity to discard planes, because all of the original
42 brushes will be saved in the map.
43 ============
44 */
EmitPlanes(void)45 void EmitPlanes( void ){
46 int i;
47 dplane_t *dp;
48 plane_t *mp;
49 int planetranslate[MAX_MAP_PLANES];
50
51 mp = mapplanes;
52 for ( i = 0 ; i < nummapplanes ; i++, mp++ )
53 {
54 dp = &dplanes[numplanes];
55 planetranslate[i] = numplanes;
56 VectorCopy( mp->normal, dp->normal );
57 dp->dist = mp->dist;
58 dp->type = mp->type;
59 numplanes++;
60 }
61 }
62
63
64 //========================================================
65
EmitMarkFace(dleaf_t * leaf_p,face_t * f)66 void EmitMarkFace( dleaf_t *leaf_p, face_t *f ){
67 int i;
68 int facenum;
69
70 while ( f->merged )
71 f = f->merged;
72
73 if ( f->split[0] ) {
74 EmitMarkFace( leaf_p, f->split[0] );
75 EmitMarkFace( leaf_p, f->split[1] );
76 return;
77 }
78
79 facenum = f->outputnumber;
80 if ( facenum == -1 ) {
81 return; // degenerate face
82
83 }
84 if ( facenum < 0 || facenum >= numfaces ) {
85 Error( "Bad leafface" );
86 }
87 for ( i = leaf_p->firstleafface ; i < numleaffaces ; i++ )
88 if ( dleaffaces[i] == facenum ) {
89 break;
90 } // merged out face
91 if ( i == numleaffaces ) {
92 if ( numleaffaces >= MAX_MAP_LEAFFACES ) {
93 Error( "MAX_MAP_LEAFFACES" );
94 }
95
96 dleaffaces[numleaffaces] = facenum;
97 numleaffaces++;
98 }
99
100 }
101
102
103 /*
104 ==================
105 EmitLeaf
106 ==================
107 */
EmitLeaf(node_t * node)108 void EmitLeaf( node_t *node ){
109 dleaf_t *leaf_p;
110 portal_t *p;
111 int s;
112 face_t *f;
113 bspbrush_t *b;
114 int i;
115 int brushnum;
116
117 // emit a leaf
118 if ( numleafs >= MAX_MAP_LEAFS ) {
119 Error( "MAX_MAP_LEAFS" );
120 }
121
122 leaf_p = &dleafs[numleafs];
123 numleafs++;
124
125 leaf_p->contents = node->contents;
126 leaf_p->cluster = node->cluster;
127 leaf_p->area = node->area;
128
129 //
130 // write bounding box info
131 //
132 VectorCopy( (short) node->mins, leaf_p->mins );
133 VectorCopy( (short) node->maxs, leaf_p->maxs );
134
135 //
136 // write the leafbrushes
137 //
138 leaf_p->firstleafbrush = numleafbrushes;
139 for ( b = node->brushlist ; b ; b = b->next )
140 {
141 if ( numleafbrushes >= MAX_MAP_LEAFBRUSHES ) {
142 Error( "MAX_MAP_LEAFBRUSHES" );
143 }
144
145 brushnum = b->original - mapbrushes;
146 for ( i = leaf_p->firstleafbrush ; i < numleafbrushes ; i++ )
147 if ( dleafbrushes[i] == brushnum ) {
148 break;
149 }
150 if ( i == numleafbrushes ) {
151 dleafbrushes[numleafbrushes] = brushnum;
152 numleafbrushes++;
153 }
154 }
155 leaf_p->numleafbrushes = numleafbrushes - leaf_p->firstleafbrush;
156
157 //
158 // write the leaffaces
159 //
160 if ( leaf_p->contents & CONTENTS_SOLID ) {
161 return; // no leaffaces in solids
162
163 }
164 leaf_p->firstleafface = numleaffaces;
165
166 for ( p = node->portals ; p ; p = p->next[s] )
167 {
168 s = ( p->nodes[1] == node );
169 f = p->face[s];
170 if ( !f ) {
171 continue; // not a visible portal
172
173 }
174 EmitMarkFace( leaf_p, f );
175 }
176
177 leaf_p->numleaffaces = numleaffaces - leaf_p->firstleafface;
178 }
179
180
181 /*
182 ==================
183 EmitFace
184 ==================
185 */
EmitFace(face_t * f)186 void EmitFace( face_t *f ){
187 dface_t *df;
188 int i;
189 int e;
190
191 f->outputnumber = -1;
192
193 if ( f->numpoints < 3 ) {
194 return; // degenerated
195 }
196 if ( f->merged || f->split[0] || f->split[1] ) {
197 return; // not a final face
198 }
199
200 // save output number so leaffaces can use
201 f->outputnumber = numfaces;
202
203 if ( numfaces >= MAX_MAP_FACES ) {
204 Error( "numfaces == MAX_MAP_FACES" );
205 }
206 df = &dfaces[numfaces];
207 numfaces++;
208
209 // planenum is used by qlight, but not quake
210 df->planenum = f->planenum & ( ~1 );
211 df->side = f->planenum & 1;
212
213 df->firstedge = numsurfedges;
214 df->numedges = f->numpoints;
215 df->texinfo = f->texinfo;
216 for ( i = 0 ; i < f->numpoints ; i++ )
217 {
218 // e = GetEdge (f->pts[i], f->pts[(i+1)%f->numpoints], f);
219 e = GetEdge2( f->vertexnums[i], f->vertexnums[( i + 1 ) % f->numpoints], f );
220 if ( numsurfedges >= MAX_MAP_SURFEDGES ) {
221 Error( "numsurfedges == MAX_MAP_SURFEDGES" );
222 }
223 dsurfedges[numsurfedges] = e;
224 numsurfedges++;
225 }
226 }
227
228 /*
229 ============
230 EmitDrawingNode_r
231 ============
232 */
EmitDrawNode_r(node_t * node)233 int EmitDrawNode_r( node_t *node ){
234 dnode_t *n;
235 face_t *f;
236 int i;
237
238 if ( node->planenum == PLANENUM_LEAF ) {
239 EmitLeaf( node );
240 return -numleafs;
241 }
242
243 // emit a node
244 if ( numnodes == MAX_MAP_NODES ) {
245 Error( "MAX_MAP_NODES" );
246 }
247 n = &dnodes[numnodes];
248 numnodes++;
249
250 VectorCopy( (short) node->mins, n->mins );
251 VectorCopy( (short) node->maxs, n->maxs );
252
253 planeused[node->planenum]++;
254 planeused[node->planenum ^ 1]++;
255
256 if ( node->planenum & 1 ) {
257 Error( "WriteDrawNodes_r: odd planenum" );
258 }
259 n->planenum = node->planenum;
260 n->firstface = numfaces;
261
262 if ( !node->faces ) {
263 c_nofaces++;
264 }
265 else{
266 c_facenodes++;
267 }
268
269 for ( f = node->faces ; f ; f = f->next )
270 EmitFace( f );
271
272 n->numfaces = numfaces - n->firstface;
273
274
275 //
276 // recursively output the other nodes
277 //
278 for ( i = 0 ; i < 2 ; i++ )
279 {
280 if ( node->children[i]->planenum == PLANENUM_LEAF ) {
281 n->children[i] = -( numleafs + 1 );
282 EmitLeaf( node->children[i] );
283 }
284 else
285 {
286 n->children[i] = numnodes;
287 EmitDrawNode_r( node->children[i] );
288 }
289 }
290
291 return n - dnodes;
292 }
293
294 //=========================================================
295
296
297 /*
298 ============
299 WriteBSP
300 ============
301 */
WriteBSP(node_t * headnode)302 void WriteBSP( node_t *headnode ){
303 int oldfaces;
304
305 c_nofaces = 0;
306 c_facenodes = 0;
307
308 Sys_FPrintf( SYS_VRB, "--- WriteBSP ---\n" );
309
310 oldfaces = numfaces;
311 dmodels[nummodels].headnode = EmitDrawNode_r( headnode );
312 EmitAreaPortals( headnode );
313
314 Sys_FPrintf( SYS_VRB, "%5i nodes with faces\n", c_facenodes );
315 Sys_FPrintf( SYS_VRB, "%5i nodes without faces\n", c_nofaces );
316 Sys_FPrintf( SYS_VRB, "%5i faces\n", numfaces - oldfaces );
317 }
318
319 //===========================================================
320
321 /*
322 ============
323 SetModelNumbers
324 ============
325 */
SetModelNumbers(void)326 void SetModelNumbers( void ){
327 int i;
328 int models;
329 char value[10];
330
331 models = 1;
332 for ( i = 1 ; i < num_entities ; i++ )
333 {
334 if ( entities[i].numbrushes ) {
335 sprintf( value, "*%i", models );
336 models++;
337 SetKeyValue( &entities[i], "model", value );
338 }
339 }
340
341 }
342
343 /*
344 ============
345 SetLightStyles
346 ============
347 */
348 #define MAX_SWITCHED_LIGHTS 32
SetLightStyles(void)349 void SetLightStyles( void ){
350 int stylenum;
351 char *t;
352 entity_t *e;
353 int i, j;
354 char value[10];
355 char lighttargets[MAX_SWITCHED_LIGHTS][64];
356
357
358 // any light that is controlled (has a targetname)
359 // must have a unique style number generated for it
360
361 stylenum = 0;
362 for ( i = 1 ; i < num_entities ; i++ )
363 {
364 e = &entities[i];
365
366 t = ValueForKey( e, "classname" );
367 if ( Q_strncasecmp( t, "light", 5 ) ) {
368 continue;
369 }
370 t = ValueForKey( e, "targetname" );
371 if ( !t[0] ) {
372 continue;
373 }
374
375 // find this targetname
376 for ( j = 0 ; j < stylenum ; j++ )
377 if ( !strcmp( lighttargets[j], t ) ) {
378 break;
379 }
380 if ( j == stylenum ) {
381 if ( stylenum == MAX_SWITCHED_LIGHTS ) {
382 Error( "stylenum == MAX_SWITCHED_LIGHTS" );
383 }
384 strcpy( lighttargets[j], t );
385 stylenum++;
386 }
387 sprintf( value, "%i", 32 + j );
388 SetKeyValue( e, "style", value );
389 }
390
391 }
392
393 //===========================================================
394
395 /*
396 ============
397 EmitBrushes
398 ============
399 */
EmitBrushes(void)400 void EmitBrushes( void ){
401 int i, j, bnum, s, x;
402 dbrush_t *db;
403 mapbrush_t *b;
404 dbrushside_t *cp;
405 vec3_t normal;
406 vec_t dist;
407 int planenum;
408
409 numbrushsides = 0;
410 numbrushes = nummapbrushes;
411
412 for ( bnum = 0 ; bnum < nummapbrushes ; bnum++ )
413 {
414 b = &mapbrushes[bnum];
415 db = &dbrushes[bnum];
416
417 db->contents = b->contents;
418 db->firstside = numbrushsides;
419 db->numsides = b->numsides;
420 for ( j = 0 ; j < b->numsides ; j++ )
421 {
422 if ( numbrushsides == MAX_MAP_BRUSHSIDES ) {
423 Error( "MAX_MAP_BRUSHSIDES" );
424 }
425 cp = &dbrushsides[numbrushsides];
426 numbrushsides++;
427 cp->planenum = b->original_sides[j].planenum;
428 cp->texinfo = b->original_sides[j].texinfo;
429 }
430
431 // add any axis planes not contained in the brush to bevel off corners
432 for ( x = 0 ; x < 3 ; x++ )
433 for ( s = -1 ; s <= 1 ; s += 2 )
434 {
435 // add the plane
436 VectorCopy( vec3_origin, normal );
437 normal[x] = (float) s;
438 if ( s == -1 ) {
439 dist = -b->mins[x];
440 }
441 else{
442 dist = b->maxs[x];
443 }
444 planenum = FindFloatPlane( normal, dist );
445 for ( i = 0 ; i < b->numsides ; i++ )
446 if ( b->original_sides[i].planenum == planenum ) {
447 break;
448 }
449 if ( i == b->numsides ) {
450 if ( numbrushsides >= MAX_MAP_BRUSHSIDES ) {
451 Error( "MAX_MAP_BRUSHSIDES" );
452 }
453
454 dbrushsides[numbrushsides].planenum = planenum;
455 dbrushsides[numbrushsides].texinfo =
456 dbrushsides[numbrushsides - 1].texinfo;
457 numbrushsides++;
458 db->numsides++;
459 }
460 }
461
462 }
463
464 }
465
466 //===========================================================
467
468 /*
469 ==================
470 BeginBSPFile
471 ==================
472 */
BeginBSPFile(void)473 void BeginBSPFile( void ){
474 // these values may actually be initialized
475 // if the file existed when loaded, so clear them explicitly
476 nummodels = 0;
477 numfaces = 0;
478 numnodes = 0;
479 numbrushsides = 0;
480 numvertexes = 0;
481 numleaffaces = 0;
482 numleafbrushes = 0;
483 numsurfedges = 0;
484
485 // edge 0 is not used, because 0 can't be negated
486 numedges = 1;
487
488 // leave vertex 0 as an error
489 numvertexes = 1;
490
491 // leave leaf 0 as an error
492 numleafs = 1;
493 dleafs[0].contents = CONTENTS_SOLID;
494 }
495
496
497 /*
498 ============
499 EndBSPFile
500 ============
501 */
EndBSPFile(void)502 void EndBSPFile( void ){
503 char path[1024];
504
505 #if 0
506 int len;
507 byte *buf;
508 #endif
509
510 EmitBrushes();
511 EmitPlanes();
512 UnparseEntities();
513
514 // load the pop
515 #if 0
516 sprintf( path, "%s/pics/pop.lmp", gamedir );
517 len = LoadFile( path, &buf );
518 memcpy( dpop, buf, sizeof( dpop ) );
519 free( buf );
520 #endif
521
522 // write the map
523 sprintf( path, "%s.bsp", source );
524 Sys_Printf( "Writing %s\n", path );
525 WriteBSPFile( path );
526 }
527
528
529 /*
530 ==================
531 BeginModel
532 ==================
533 */
534 int firstmodleaf;
535 extern int firstmodeledge;
536 extern int firstmodelface;
BeginModel(void)537 void BeginModel( void ){
538 dmodel_t *mod;
539 int start, end;
540 mapbrush_t *b;
541 int j;
542 entity_t *e;
543 vec3_t mins, maxs;
544
545 if ( nummodels == MAX_MAP_MODELS ) {
546 Error( "MAX_MAP_MODELS" );
547 }
548 mod = &dmodels[nummodels];
549
550 mod->firstface = numfaces;
551
552 firstmodleaf = numleafs;
553 firstmodeledge = numedges;
554 firstmodelface = numfaces;
555
556 //
557 // bound the brushes
558 //
559 e = &entities[entity_num];
560
561 start = e->firstbrush;
562 end = start + e->numbrushes;
563 ClearBounds( mins, maxs );
564
565 for ( j = start ; j < end ; j++ )
566 {
567 b = &mapbrushes[j];
568 if ( !b->numsides ) {
569 continue; // not a real brush (origin brush)
570 }
571 AddPointToBounds( b->mins, mins, maxs );
572 AddPointToBounds( b->maxs, mins, maxs );
573 }
574
575 VectorCopy( mins, mod->mins );
576 VectorCopy( maxs, mod->maxs );
577 }
578
579
580 /*
581 ==================
582 EndModel
583 ==================
584 */
EndModel(void)585 void EndModel( void ){
586 dmodel_t *mod;
587
588 mod = &dmodels[nummodels];
589
590 mod->numfaces = numfaces - mod->firstface;
591
592 nummodels++;
593 }
594