]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/extra/bsp/qbsp3/writebsp.c
Q2Tools source - didn't import this in initially
[xonotic/netradiant.git] / tools / quake2 / extra / bsp / qbsp3 / writebsp.c
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 */
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
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 */
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 */
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 */
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 */
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 */
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
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 */
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 */
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 */
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;
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 */
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