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