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