2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
28 =========================================================
\r
30 ONLY SAVE OUT PLANES THAT ARE ACTUALLY USED AS NODES
\r
32 =========================================================
\r
35 int planeused[MAX_MAP_PLANES];
\r
41 There is no oportunity to discard planes, because all of the original
\r
42 brushes will be saved in the map.
\r
45 void EmitPlanes (void)
\r
50 int planetranslate[MAX_MAP_PLANES];
\r
53 for (i=0 ; i<nummapplanes ; i++, mp++)
\r
55 dp = &dplanes[numplanes];
\r
56 planetranslate[i] = numplanes;
\r
57 VectorCopy ( mp->normal, dp->normal);
\r
58 dp->dist = mp->dist;
\r
59 dp->type = mp->type;
\r
65 //========================================================
\r
67 void EmitMarkFace (dleaf_t *leaf_p, face_t *f)
\r
77 EmitMarkFace (leaf_p, f->split[0]);
\r
78 EmitMarkFace (leaf_p, f->split[1]);
\r
82 facenum = f->outputnumber;
\r
84 return; // degenerate face
\r
86 if (facenum < 0 || facenum >= numfaces)
\r
87 Error ("Bad leafface");
\r
88 for (i=leaf_p->firstleafface ; i<numleaffaces ; i++)
\r
89 if (dleaffaces[i] == facenum)
\r
90 break; // merged out face
\r
91 if (i == numleaffaces)
\r
93 if (numleaffaces >= MAX_MAP_LEAFFACES)
\r
94 Error ("MAX_MAP_LEAFFACES");
\r
96 dleaffaces[numleaffaces] = facenum;
\r
108 void EmitLeaf (node_t *node)
\r
119 if (numleafs >= MAX_MAP_LEAFS)
\r
120 Error ("MAX_MAP_LEAFS");
\r
122 leaf_p = &dleafs[numleafs];
\r
125 leaf_p->contents = node->contents;
\r
126 leaf_p->cluster = node->cluster;
\r
127 leaf_p->area = node->area;
\r
130 // write bounding box info
\r
132 VectorCopy ((short) node->mins, leaf_p->mins);
\r
133 VectorCopy ((short) node->maxs, leaf_p->maxs);
\r
136 // write the leafbrushes
\r
138 leaf_p->firstleafbrush = numleafbrushes;
\r
139 for (b=node->brushlist ; b ; b=b->next)
\r
141 if (numleafbrushes >= MAX_MAP_LEAFBRUSHES)
\r
142 Error ("MAX_MAP_LEAFBRUSHES");
\r
144 brushnum = b->original - mapbrushes;
\r
145 for (i=leaf_p->firstleafbrush ; i<numleafbrushes ; i++)
\r
146 if (dleafbrushes[i] == brushnum)
\r
148 if (i == numleafbrushes)
\r
150 dleafbrushes[numleafbrushes] = brushnum;
\r
154 leaf_p->numleafbrushes = numleafbrushes - leaf_p->firstleafbrush;
\r
157 // write the leaffaces
\r
159 if (leaf_p->contents & CONTENTS_SOLID)
\r
160 return; // no leaffaces in solids
\r
162 leaf_p->firstleafface = numleaffaces;
\r
164 for (p = node->portals ; p ; p = p->next[s])
\r
166 s = (p->nodes[1] == node);
\r
169 continue; // not a visible portal
\r
171 EmitMarkFace (leaf_p, f);
\r
174 leaf_p->numleaffaces = numleaffaces - leaf_p->firstleafface;
\r
183 void EmitFace (face_t *f)
\r
189 f->outputnumber = -1;
\r
191 if (f->numpoints < 3)
\r
193 return; // degenerated
\r
195 if (f->merged || f->split[0] || f->split[1])
\r
197 return; // not a final face
\r
200 // save output number so leaffaces can use
\r
201 f->outputnumber = numfaces;
\r
203 if (numfaces >= MAX_MAP_FACES)
\r
204 Error ("numfaces == MAX_MAP_FACES");
\r
205 df = &dfaces[numfaces];
\r
208 // planenum is used by qlight, but not quake
\r
209 df->planenum = f->planenum & (~1);
\r
210 df->side = f->planenum & 1;
\r
212 df->firstedge = numsurfedges;
\r
213 df->numedges = f->numpoints;
\r
214 df->texinfo = f->texinfo;
\r
215 for (i=0 ; i<f->numpoints ; i++)
\r
217 // e = GetEdge (f->pts[i], f->pts[(i+1)%f->numpoints], f);
\r
218 e = GetEdge2 (f->vertexnums[i], f->vertexnums[(i+1)%f->numpoints], f);
\r
219 if (numsurfedges >= MAX_MAP_SURFEDGES)
\r
220 Error ("numsurfedges == MAX_MAP_SURFEDGES");
\r
221 dsurfedges[numsurfedges] = e;
\r
231 int EmitDrawNode_r (node_t *node)
\r
237 if (node->planenum == PLANENUM_LEAF)
\r
244 if (numnodes == MAX_MAP_NODES)
\r
245 Error ("MAX_MAP_NODES");
\r
246 n = &dnodes[numnodes];
\r
249 VectorCopy ((short) node->mins, n->mins);
\r
250 VectorCopy ((short) node->maxs, n->maxs);
\r
252 planeused[node->planenum]++;
\r
253 planeused[node->planenum^1]++;
\r
255 if (node->planenum & 1)
\r
256 Error ("WriteDrawNodes_r: odd planenum");
\r
257 n->planenum = node->planenum;
\r
258 n->firstface = numfaces;
\r
265 for (f=node->faces ; f ; f=f->next)
\r
268 n->numfaces = numfaces - n->firstface;
\r
272 // recursively output the other nodes
\r
274 for (i=0 ; i<2 ; i++)
\r
276 if (node->children[i]->planenum == PLANENUM_LEAF)
\r
278 n->children[i] = -(numleafs + 1);
\r
279 EmitLeaf (node->children[i]);
\r
283 n->children[i] = numnodes;
\r
284 EmitDrawNode_r (node->children[i]);
\r
291 //=========================================================
\r
299 void WriteBSP (node_t *headnode)
\r
306 Sys_FPrintf( SYS_VRB, "--- WriteBSP ---\n");
\r
308 oldfaces = numfaces;
\r
309 dmodels[nummodels].headnode = EmitDrawNode_r (headnode);
\r
310 EmitAreaPortals (headnode);
\r
312 Sys_FPrintf( SYS_VRB, "%5i nodes with faces\n", c_facenodes);
\r
313 Sys_FPrintf( SYS_VRB, "%5i nodes without faces\n", c_nofaces);
\r
314 Sys_FPrintf( SYS_VRB, "%5i faces\n", numfaces-oldfaces);
\r
317 //===========================================================
\r
324 void SetModelNumbers (void)
\r
331 for (i=1 ; i<num_entities ; i++)
\r
333 if (entities[i].numbrushes)
\r
335 sprintf (value, "*%i", models);
\r
337 SetKeyValue (&entities[i], "model", value);
\r
348 #define MAX_SWITCHED_LIGHTS 32
\r
349 void SetLightStyles (void)
\r
356 char lighttargets[MAX_SWITCHED_LIGHTS][64];
\r
359 // any light that is controlled (has a targetname)
\r
360 // must have a unique style number generated for it
\r
363 for (i=1 ; i<num_entities ; i++)
\r
367 t = ValueForKey (e, "classname");
\r
368 if (Q_strncasecmp (t, "light", 5))
\r
370 t = ValueForKey (e, "targetname");
\r
374 // find this targetname
\r
375 for (j=0 ; j<stylenum ; j++)
\r
376 if (!strcmp (lighttargets[j], t))
\r
380 if (stylenum == MAX_SWITCHED_LIGHTS)
\r
381 Error ("stylenum == MAX_SWITCHED_LIGHTS");
\r
382 strcpy (lighttargets[j], t);
\r
385 sprintf (value, "%i", 32 + j);
\r
386 SetKeyValue (e, "style", value);
\r
391 //===========================================================
\r
398 void EmitBrushes (void)
\r
400 int i, j, bnum, s, x;
\r
409 numbrushes = nummapbrushes;
\r
411 for (bnum=0 ; bnum<nummapbrushes ; bnum++)
\r
413 b = &mapbrushes[bnum];
\r
414 db = &dbrushes[bnum];
\r
416 db->contents = b->contents;
\r
417 db->firstside = numbrushsides;
\r
418 db->numsides = b->numsides;
\r
419 for (j=0 ; j<b->numsides ; j++)
\r
421 if (numbrushsides == MAX_MAP_BRUSHSIDES)
\r
422 Error ("MAX_MAP_BRUSHSIDES");
\r
423 cp = &dbrushsides[numbrushsides];
\r
425 cp->planenum = b->original_sides[j].planenum;
\r
426 cp->texinfo = b->original_sides[j].texinfo;
\r
429 // add any axis planes not contained in the brush to bevel off corners
\r
430 for (x=0 ; x<3 ; x++)
\r
431 for (s=-1 ; s<=1 ; s+=2)
\r
434 VectorCopy (vec3_origin, normal);
\r
435 normal[x] = (float) s;
\r
437 dist = -b->mins[x];
\r
440 planenum = FindFloatPlane (normal, dist);
\r
441 for (i=0 ; i<b->numsides ; i++)
\r
442 if (b->original_sides[i].planenum == planenum)
\r
444 if (i == b->numsides)
\r
446 if (numbrushsides >= MAX_MAP_BRUSHSIDES)
\r
447 Error ("MAX_MAP_BRUSHSIDES");
\r
449 dbrushsides[numbrushsides].planenum = planenum;
\r
450 dbrushsides[numbrushsides].texinfo =
\r
451 dbrushsides[numbrushsides-1].texinfo;
\r
461 //===========================================================
\r
468 void BeginBSPFile (void)
\r
470 // these values may actually be initialized
\r
471 // if the file existed when loaded, so clear them explicitly
\r
478 numleafbrushes = 0;
\r
481 // edge 0 is not used, because 0 can't be negated
\r
484 // leave vertex 0 as an error
\r
487 // leave leaf 0 as an error
\r
489 dleafs[0].contents = CONTENTS_SOLID;
\r
498 void EndBSPFile (void)
\r
509 UnparseEntities ();
\r
513 sprintf (path, "%s/pics/pop.lmp", gamedir);
\r
514 len = LoadFile (path, &buf);
\r
515 memcpy (dpop, buf, sizeof(dpop));
\r
520 sprintf (path, "%s.bsp", source);
\r
521 Sys_Printf ("Writing %s\n", path);
\r
522 WriteBSPFile (path);
\r
532 extern int firstmodeledge;
\r
533 extern int firstmodelface;
\r
534 void BeginModel (void)
\r
543 if (nummodels == MAX_MAP_MODELS)
\r
544 Error ("MAX_MAP_MODELS");
\r
545 mod = &dmodels[nummodels];
\r
547 mod->firstface = numfaces;
\r
549 firstmodleaf = numleafs;
\r
550 firstmodeledge = numedges;
\r
551 firstmodelface = numfaces;
\r
554 // bound the brushes
\r
556 e = &entities[entity_num];
\r
558 start = e->firstbrush;
\r
559 end = start + e->numbrushes;
\r
560 ClearBounds (mins, maxs);
\r
562 for (j=start ; j<end ; j++)
\r
564 b = &mapbrushes[j];
\r
566 continue; // not a real brush (origin brush)
\r
567 AddPointToBounds (b->mins, mins, maxs);
\r
568 AddPointToBounds (b->maxs, mins, maxs);
\r
571 VectorCopy (mins, mod->mins);
\r
572 VectorCopy (maxs, mod->maxs);
\r
581 void EndModel (void)
\r
585 mod = &dmodels[nummodels];
\r
587 mod->numfaces = numfaces - mod->firstface;
\r