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