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