]> de.git.xonotic.org Git - xonotic/netradiant.git/blobdiff - tools/quake2/q2map/writebsp.c
eol style
[xonotic/netradiant.git] / tools / quake2 / q2map / writebsp.c
index 083f0ea769190ef39a035e4e3b9cc8305d89c0e5..8c45d5305c02672aec05d09ac286fa6eb3b44ba1 100644 (file)
-/*\r
-Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
-For a list of contributors, see the accompanying CONTRIBUTORS file.\r
-\r
-This file is part of GtkRadiant.\r
-\r
-GtkRadiant is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU General Public License as published by\r
-the Free Software Foundation; either version 2 of the License, or\r
-(at your option) any later version.\r
-\r
-GtkRadiant is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU General Public License for more details.\r
-\r
-You should have received a copy of the GNU General Public License\r
-along with GtkRadiant; if not, write to the Free Software\r
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\r
-*/\r
-#include "qbsp.h"\r
-\r
-int            c_nofaces;\r
-int            c_facenodes;\r
-\r
-\r
-/*\r
-=========================================================\r
-\r
-ONLY SAVE OUT PLANES THAT ARE ACTUALLY USED AS NODES\r
-\r
-=========================================================\r
-*/\r
-\r
-int            planeused[MAX_MAP_PLANES];\r
-\r
-/*\r
-============\r
-EmitPlanes\r
-\r
-There is no oportunity to discard planes, because all of the original\r
-brushes will be saved in the map.\r
-============\r
-*/\r
-void EmitPlanes (void)\r
-{\r
-       int                     i;\r
-       dplane_t        *dp;\r
-       plane_t         *mp;\r
-       int             planetranslate[MAX_MAP_PLANES];\r
-\r
-       mp = mapplanes;\r
-       for (i=0 ; i<nummapplanes ; i++, mp++)\r
-       {\r
-               dp = &dplanes[numplanes];\r
-               planetranslate[i] = numplanes;\r
-               VectorCopy ( mp->normal, dp->normal);\r
-               dp->dist = mp->dist;\r
-               dp->type = mp->type;\r
-               numplanes++;\r
-       }\r
-}\r
-\r
-\r
-//========================================================\r
-\r
-void EmitMarkFace (dleaf_t *leaf_p, face_t *f)\r
-{\r
-       int                     i;\r
-       int                     facenum;\r
-\r
-       while (f->merged)\r
-               f = f->merged;\r
-\r
-       if (f->split[0])\r
-       {\r
-               EmitMarkFace (leaf_p, f->split[0]);\r
-               EmitMarkFace (leaf_p, f->split[1]);\r
-               return;\r
-       }\r
-\r
-       facenum = f->outputnumber;\r
-       if (facenum == -1)\r
-               return; // degenerate face\r
-\r
-       if (facenum < 0 || facenum >= numfaces)\r
-               Error ("Bad leafface");\r
-       for (i=leaf_p->firstleafface ; i<numleaffaces ; i++)\r
-               if (dleaffaces[i] == facenum)\r
-                       break;          // merged out face\r
-       if (i == numleaffaces)\r
-       {\r
-               if (numleaffaces >= MAX_MAP_LEAFFACES)\r
-                       Error ("MAX_MAP_LEAFFACES");\r
-\r
-               dleaffaces[numleaffaces] =  facenum;\r
-               numleaffaces++;\r
-       }\r
-\r
-}\r
-\r
-\r
-/*\r
-==================\r
-EmitLeaf\r
-==================\r
-*/\r
-void EmitLeaf (node_t *node)\r
-{\r
-       dleaf_t         *leaf_p;\r
-       portal_t        *p;\r
-       int                     s;\r
-       face_t          *f;\r
-       bspbrush_t      *b;\r
-       int                     i;\r
-       int                     brushnum;\r
-\r
-       // emit a leaf\r
-       if (numleafs >= MAX_MAP_LEAFS)\r
-               Error ("MAX_MAP_LEAFS");\r
-\r
-       leaf_p = &dleafs[numleafs];\r
-       numleafs++;\r
-\r
-       leaf_p->contents = node->contents;\r
-       leaf_p->cluster = node->cluster;\r
-       leaf_p->area = node->area;\r
-\r
-       //\r
-       // write bounding box info\r
-       //      \r
-       VectorCopy ((short) node->mins, leaf_p->mins);\r
-       VectorCopy ((short) node->maxs, leaf_p->maxs);\r
-       \r
-       //\r
-       // write the leafbrushes\r
-       //\r
-       leaf_p->firstleafbrush = numleafbrushes;\r
-       for (b=node->brushlist ; b ; b=b->next)\r
-       {\r
-               if (numleafbrushes >= MAX_MAP_LEAFBRUSHES)\r
-                       Error ("MAX_MAP_LEAFBRUSHES");\r
-\r
-               brushnum = b->original - mapbrushes;\r
-               for (i=leaf_p->firstleafbrush ; i<numleafbrushes ; i++)\r
-                       if (dleafbrushes[i] == brushnum)\r
-                               break;\r
-               if (i == numleafbrushes)\r
-               {\r
-                       dleafbrushes[numleafbrushes] = brushnum;\r
-                       numleafbrushes++;\r
-               }\r
-       }\r
-       leaf_p->numleafbrushes = numleafbrushes - leaf_p->firstleafbrush;\r
-\r
-       //\r
-       // write the leaffaces\r
-       //\r
-       if (leaf_p->contents & CONTENTS_SOLID)\r
-               return;         // no leaffaces in solids\r
-\r
-       leaf_p->firstleafface = numleaffaces;\r
-\r
-       for (p = node->portals ; p ; p = p->next[s])    \r
-       {\r
-               s = (p->nodes[1] == node);\r
-               f = p->face[s];\r
-               if (!f)\r
-                       continue;       // not a visible portal\r
-\r
-               EmitMarkFace (leaf_p, f);\r
-       }\r
-       \r
-       leaf_p->numleaffaces = numleaffaces - leaf_p->firstleafface;\r
-}\r
-\r
-\r
-/*\r
-==================\r
-EmitFace\r
-==================\r
-*/\r
-void EmitFace (face_t *f)\r
-{\r
-       dface_t *df;\r
-       int             i;\r
-       int             e;\r
-\r
-       f->outputnumber = -1;\r
-\r
-       if (f->numpoints < 3)\r
-       {\r
-               return;         // degenerated\r
-       }\r
-       if (f->merged || f->split[0] || f->split[1])\r
-       {\r
-               return;         // not a final face\r
-       }\r
-\r
-       // save output number so leaffaces can use\r
-       f->outputnumber = numfaces;\r
-\r
-       if (numfaces >= MAX_MAP_FACES)\r
-               Error ("numfaces == MAX_MAP_FACES");\r
-       df = &dfaces[numfaces];\r
-       numfaces++;\r
-\r
-       // planenum is used by qlight, but not quake\r
-       df->planenum = f->planenum & (~1);\r
-       df->side = f->planenum & 1;\r
-\r
-       df->firstedge = numsurfedges;\r
-       df->numedges = f->numpoints;\r
-       df->texinfo = f->texinfo;\r
-       for (i=0 ; i<f->numpoints ; i++)\r
-       {\r
-//             e = GetEdge (f->pts[i], f->pts[(i+1)%f->numpoints], f);\r
-               e = GetEdge2 (f->vertexnums[i], f->vertexnums[(i+1)%f->numpoints], f);\r
-               if (numsurfedges >= MAX_MAP_SURFEDGES)\r
-                       Error ("numsurfedges == MAX_MAP_SURFEDGES");\r
-               dsurfedges[numsurfedges] = e;\r
-               numsurfedges++;\r
-       }\r
-}\r
-\r
-/*\r
-============\r
-EmitDrawingNode_r\r
-============\r
-*/\r
-int EmitDrawNode_r (node_t *node)\r
-{\r
-       dnode_t *n;\r
-       face_t  *f;\r
-       int             i;\r
-\r
-       if (node->planenum == PLANENUM_LEAF)\r
-       {\r
-               EmitLeaf (node);\r
-               return -numleafs;\r
-       }\r
-\r
-       // emit a node  \r
-       if (numnodes == MAX_MAP_NODES)\r
-               Error ("MAX_MAP_NODES");\r
-       n = &dnodes[numnodes];\r
-       numnodes++;\r
-\r
-       VectorCopy ((short) node->mins, n->mins);\r
-       VectorCopy ((short) node->maxs, n->maxs);\r
-\r
-       planeused[node->planenum]++;\r
-       planeused[node->planenum^1]++;\r
-\r
-       if (node->planenum & 1)\r
-               Error ("WriteDrawNodes_r: odd planenum");\r
-       n->planenum = node->planenum;\r
-       n->firstface = numfaces;\r
-\r
-       if (!node->faces)\r
-               c_nofaces++;\r
-       else\r
-               c_facenodes++;\r
-\r
-       for (f=node->faces ; f ; f=f->next)\r
-               EmitFace (f);\r
-\r
-       n->numfaces = numfaces - n->firstface;\r
-\r
-\r
-       //\r
-       // recursively output the other nodes\r
-       //      \r
-       for (i=0 ; i<2 ; i++)\r
-       {\r
-               if (node->children[i]->planenum == PLANENUM_LEAF)\r
-               {\r
-                       n->children[i] = -(numleafs + 1);\r
-                       EmitLeaf (node->children[i]);\r
-               }\r
-               else\r
-               {\r
-                       n->children[i] = numnodes;      \r
-                       EmitDrawNode_r (node->children[i]);\r
-               }\r
-       }\r
-\r
-       return n - dnodes;\r
-}\r
-\r
-//=========================================================\r
-\r
-\r
-/*\r
-============\r
-WriteBSP\r
-============\r
-*/\r
-void WriteBSP (node_t *headnode)\r
-{\r
-       int             oldfaces;\r
-\r
-       c_nofaces = 0;\r
-       c_facenodes = 0;\r
-\r
-       Sys_FPrintf( SYS_VRB, "--- WriteBSP ---\n");\r
-\r
-       oldfaces = numfaces;\r
-       dmodels[nummodels].headnode = EmitDrawNode_r (headnode);\r
-       EmitAreaPortals (headnode);\r
-\r
-       Sys_FPrintf( SYS_VRB, "%5i nodes with faces\n", c_facenodes);\r
-       Sys_FPrintf( SYS_VRB, "%5i nodes without faces\n", c_nofaces);\r
-       Sys_FPrintf( SYS_VRB, "%5i faces\n", numfaces-oldfaces);\r
-}\r
-\r
-//===========================================================\r
-\r
-/*\r
-============\r
-SetModelNumbers\r
-============\r
-*/\r
-void SetModelNumbers (void)\r
-{\r
-       int             i;\r
-       int             models;\r
-       char    value[10];\r
-\r
-       models = 1;\r
-       for (i=1 ; i<num_entities ; i++)\r
-       {\r
-               if (entities[i].numbrushes)\r
-               {\r
-                       sprintf (value, "*%i", models);\r
-                       models++;\r
-                       SetKeyValue (&entities[i], "model", value);\r
-               }\r
-       }\r
-\r
-}\r
-\r
-/*\r
-============\r
-SetLightStyles\r
-============\r
-*/\r
-#define        MAX_SWITCHED_LIGHTS     32\r
-void SetLightStyles (void)\r
-{\r
-       int             stylenum;\r
-       char    *t;\r
-       entity_t        *e;\r
-       int             i, j;\r
-       char    value[10];\r
-       char    lighttargets[MAX_SWITCHED_LIGHTS][64];\r
-\r
-\r
-       // any light that is controlled (has a targetname)\r
-       // must have a unique style number generated for it\r
-\r
-       stylenum = 0;\r
-       for (i=1 ; i<num_entities ; i++)\r
-       {\r
-               e = &entities[i];\r
-\r
-               t = ValueForKey (e, "classname");\r
-               if (Q_strncasecmp (t, "light", 5))\r
-                       continue;\r
-               t = ValueForKey (e, "targetname");\r
-               if (!t[0])\r
-                       continue;\r
-               \r
-               // find this targetname\r
-               for (j=0 ; j<stylenum ; j++)\r
-                       if (!strcmp (lighttargets[j], t))\r
-                               break;\r
-               if (j == stylenum)\r
-               {\r
-                       if (stylenum == MAX_SWITCHED_LIGHTS)\r
-                               Error ("stylenum == MAX_SWITCHED_LIGHTS");\r
-                       strcpy (lighttargets[j], t);\r
-                       stylenum++;\r
-               }\r
-               sprintf (value, "%i", 32 + j);\r
-               SetKeyValue (e, "style", value);\r
-       }\r
-\r
-}\r
-\r
-//===========================================================\r
-\r
-/*\r
-============\r
-EmitBrushes\r
-============\r
-*/\r
-void EmitBrushes (void)\r
-{\r
-       int                     i, j, bnum, s, x;\r
-       dbrush_t        *db;\r
-       mapbrush_t              *b;\r
-       dbrushside_t    *cp;\r
-       vec3_t          normal;\r
-       vec_t           dist;\r
-       int                     planenum;\r
-\r
-       numbrushsides = 0;\r
-       numbrushes = nummapbrushes;\r
-\r
-       for (bnum=0 ; bnum<nummapbrushes ; bnum++)\r
-       {\r
-               b = &mapbrushes[bnum];\r
-               db = &dbrushes[bnum];\r
-\r
-               db->contents = b->contents;\r
-               db->firstside = numbrushsides;\r
-               db->numsides = b->numsides;\r
-               for (j=0 ; j<b->numsides ; j++)\r
-               {\r
-                       if (numbrushsides == MAX_MAP_BRUSHSIDES)\r
-                               Error ("MAX_MAP_BRUSHSIDES");\r
-                       cp = &dbrushsides[numbrushsides];\r
-                       numbrushsides++;\r
-                       cp->planenum = b->original_sides[j].planenum;\r
-                       cp->texinfo = b->original_sides[j].texinfo;\r
-               }\r
-\r
-               // add any axis planes not contained in the brush to bevel off corners\r
-               for (x=0 ; x<3 ; x++)\r
-                       for (s=-1 ; s<=1 ; s+=2)\r
-                       {\r
-                       // add the plane\r
-                               VectorCopy (vec3_origin, normal);\r
-                               normal[x] = (float) s;\r
-                               if (s == -1)\r
-                                       dist = -b->mins[x];\r
-                               else\r
-                                       dist = b->maxs[x];\r
-                               planenum = FindFloatPlane (normal, dist);\r
-                               for (i=0 ; i<b->numsides ; i++)\r
-                                       if (b->original_sides[i].planenum == planenum)\r
-                                               break;\r
-                               if (i == b->numsides)\r
-                               {\r
-                                       if (numbrushsides >= MAX_MAP_BRUSHSIDES)\r
-                                               Error ("MAX_MAP_BRUSHSIDES");\r
-\r
-                                       dbrushsides[numbrushsides].planenum = planenum;\r
-                                       dbrushsides[numbrushsides].texinfo =\r
-                                               dbrushsides[numbrushsides-1].texinfo;\r
-                                       numbrushsides++;\r
-                                       db->numsides++;\r
-                               }\r
-                       }\r
-\r
-       }\r
-\r
-}\r
-\r
-//===========================================================\r
-\r
-/*\r
-==================\r
-BeginBSPFile\r
-==================\r
-*/\r
-void BeginBSPFile (void)\r
-{\r
-       // these values may actually be initialized\r
-       // if the file existed when loaded, so clear them explicitly\r
-       nummodels = 0;\r
-       numfaces = 0;\r
-       numnodes = 0;\r
-       numbrushsides = 0;\r
-       numvertexes = 0;\r
-       numleaffaces = 0;\r
-       numleafbrushes = 0;\r
-       numsurfedges = 0;\r
-\r
-       // edge 0 is not used, because 0 can't be negated\r
-       numedges = 1;\r
-\r
-       // leave vertex 0 as an error\r
-       numvertexes = 1;\r
-\r
-       // leave leaf 0 as an error\r
-       numleafs = 1;\r
-       dleafs[0].contents = CONTENTS_SOLID;\r
-}\r
-\r
-\r
-/*\r
-============\r
-EndBSPFile\r
-============\r
-*/\r
-void EndBSPFile (void)\r
-{\r
-       char    path[1024];\r
-\r
-#if 0\r
-       int             len;\r
-       byte    *buf;\r
-#endif\r
-\r
-       EmitBrushes ();\r
-       EmitPlanes ();\r
-       UnparseEntities ();\r
-\r
-       // load the pop\r
-#if 0\r
-       sprintf (path, "%s/pics/pop.lmp", gamedir);\r
-       len = LoadFile (path, &buf);\r
-       memcpy (dpop, buf, sizeof(dpop));\r
-       free (buf);\r
-#endif\r
-\r
-       // write the map\r
-       sprintf (path, "%s.bsp", source);\r
-       Sys_Printf ("Writing %s\n", path);\r
-       WriteBSPFile (path);\r
-}\r
-\r
-\r
-/*\r
-==================\r
-BeginModel\r
-==================\r
-*/\r
-int    firstmodleaf;\r
-extern int firstmodeledge;\r
-extern int     firstmodelface;\r
-void BeginModel (void)\r
-{\r
-       dmodel_t        *mod;\r
-       int                     start, end;\r
-       mapbrush_t      *b;\r
-       int                     j;\r
-       entity_t        *e;\r
-       vec3_t          mins, maxs;\r
-\r
-       if (nummodels == MAX_MAP_MODELS)\r
-               Error ("MAX_MAP_MODELS");\r
-       mod = &dmodels[nummodels];\r
-\r
-       mod->firstface = numfaces;\r
-\r
-       firstmodleaf = numleafs;\r
-       firstmodeledge = numedges;\r
-       firstmodelface = numfaces;\r
-\r
-       //\r
-       // bound the brushes\r
-       //\r
-       e = &entities[entity_num];\r
-\r
-       start = e->firstbrush;\r
-       end = start + e->numbrushes;\r
-       ClearBounds (mins, maxs);\r
-\r
-       for (j=start ; j<end ; j++)\r
-       {\r
-               b = &mapbrushes[j];\r
-               if (!b->numsides)\r
-                       continue;       // not a real brush (origin brush)\r
-               AddPointToBounds (b->mins, mins, maxs);\r
-               AddPointToBounds (b->maxs, mins, maxs);\r
-       }\r
-\r
-       VectorCopy (mins, mod->mins);\r
-       VectorCopy (maxs, mod->maxs);\r
-}\r
-\r
-\r
-/*\r
-==================\r
-EndModel\r
-==================\r
-*/\r
-void EndModel (void)\r
-{\r
-       dmodel_t        *mod;\r
-\r
-       mod = &dmodels[nummodels];\r
-\r
-       mod->numfaces = numfaces - mod->firstface;\r
-\r
-       nummodels++;\r
-}\r
-\r
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+GtkRadiant is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include "qbsp.h"
+
+int            c_nofaces;
+int            c_facenodes;
+
+
+/*
+=========================================================
+
+ONLY SAVE OUT PLANES THAT ARE ACTUALLY USED AS NODES
+
+=========================================================
+*/
+
+int            planeused[MAX_MAP_PLANES];
+
+/*
+============
+EmitPlanes
+
+There is no oportunity to discard planes, because all of the original
+brushes will be saved in the map.
+============
+*/
+void EmitPlanes (void)
+{
+       int                     i;
+       dplane_t        *dp;
+       plane_t         *mp;
+       int             planetranslate[MAX_MAP_PLANES];
+
+       mp = mapplanes;
+       for (i=0 ; i<nummapplanes ; i++, mp++)
+       {
+               dp = &dplanes[numplanes];
+               planetranslate[i] = numplanes;
+               VectorCopy ( mp->normal, dp->normal);
+               dp->dist = mp->dist;
+               dp->type = mp->type;
+               numplanes++;
+       }
+}
+
+
+//========================================================
+
+void EmitMarkFace (dleaf_t *leaf_p, face_t *f)
+{
+       int                     i;
+       int                     facenum;
+
+       while (f->merged)
+               f = f->merged;
+
+       if (f->split[0])
+       {
+               EmitMarkFace (leaf_p, f->split[0]);
+               EmitMarkFace (leaf_p, f->split[1]);
+               return;
+       }
+
+       facenum = f->outputnumber;
+       if (facenum == -1)
+               return; // degenerate face
+
+       if (facenum < 0 || facenum >= numfaces)
+               Error ("Bad leafface");
+       for (i=leaf_p->firstleafface ; i<numleaffaces ; i++)
+               if (dleaffaces[i] == facenum)
+                       break;          // merged out face
+       if (i == numleaffaces)
+       {
+               if (numleaffaces >= MAX_MAP_LEAFFACES)
+                       Error ("MAX_MAP_LEAFFACES");
+
+               dleaffaces[numleaffaces] =  facenum;
+               numleaffaces++;
+       }
+
+}
+
+
+/*
+==================
+EmitLeaf
+==================
+*/
+void EmitLeaf (node_t *node)
+{
+       dleaf_t         *leaf_p;
+       portal_t        *p;
+       int                     s;
+       face_t          *f;
+       bspbrush_t      *b;
+       int                     i;
+       int                     brushnum;
+
+       // emit a leaf
+       if (numleafs >= MAX_MAP_LEAFS)
+               Error ("MAX_MAP_LEAFS");
+
+       leaf_p = &dleafs[numleafs];
+       numleafs++;
+
+       leaf_p->contents = node->contents;
+       leaf_p->cluster = node->cluster;
+       leaf_p->area = node->area;
+
+       //
+       // write bounding box info
+       //      
+       VectorCopy ((short) node->mins, leaf_p->mins);
+       VectorCopy ((short) node->maxs, leaf_p->maxs);
+       
+       //
+       // write the leafbrushes
+       //
+       leaf_p->firstleafbrush = numleafbrushes;
+       for (b=node->brushlist ; b ; b=b->next)
+       {
+               if (numleafbrushes >= MAX_MAP_LEAFBRUSHES)
+                       Error ("MAX_MAP_LEAFBRUSHES");
+
+               brushnum = b->original - mapbrushes;
+               for (i=leaf_p->firstleafbrush ; i<numleafbrushes ; i++)
+                       if (dleafbrushes[i] == brushnum)
+                               break;
+               if (i == numleafbrushes)
+               {
+                       dleafbrushes[numleafbrushes] = brushnum;
+                       numleafbrushes++;
+               }
+       }
+       leaf_p->numleafbrushes = numleafbrushes - leaf_p->firstleafbrush;
+
+       //
+       // write the leaffaces
+       //
+       if (leaf_p->contents & CONTENTS_SOLID)
+               return;         // no leaffaces in solids
+
+       leaf_p->firstleafface = numleaffaces;
+
+       for (p = node->portals ; p ; p = p->next[s])    
+       {
+               s = (p->nodes[1] == node);
+               f = p->face[s];
+               if (!f)
+                       continue;       // not a visible portal
+
+               EmitMarkFace (leaf_p, f);
+       }
+       
+       leaf_p->numleaffaces = numleaffaces - leaf_p->firstleafface;
+}
+
+
+/*
+==================
+EmitFace
+==================
+*/
+void EmitFace (face_t *f)
+{
+       dface_t *df;
+       int             i;
+       int             e;
+
+       f->outputnumber = -1;
+
+       if (f->numpoints < 3)
+       {
+               return;         // degenerated
+       }
+       if (f->merged || f->split[0] || f->split[1])
+       {
+               return;         // not a final face
+       }
+
+       // save output number so leaffaces can use
+       f->outputnumber = numfaces;
+
+       if (numfaces >= MAX_MAP_FACES)
+               Error ("numfaces == MAX_MAP_FACES");
+       df = &dfaces[numfaces];
+       numfaces++;
+
+       // planenum is used by qlight, but not quake
+       df->planenum = f->planenum & (~1);
+       df->side = f->planenum & 1;
+
+       df->firstedge = numsurfedges;
+       df->numedges = f->numpoints;
+       df->texinfo = f->texinfo;
+       for (i=0 ; i<f->numpoints ; i++)
+       {
+//             e = GetEdge (f->pts[i], f->pts[(i+1)%f->numpoints], f);
+               e = GetEdge2 (f->vertexnums[i], f->vertexnums[(i+1)%f->numpoints], f);
+               if (numsurfedges >= MAX_MAP_SURFEDGES)
+                       Error ("numsurfedges == MAX_MAP_SURFEDGES");
+               dsurfedges[numsurfedges] = e;
+               numsurfedges++;
+       }
+}
+
+/*
+============
+EmitDrawingNode_r
+============
+*/
+int EmitDrawNode_r (node_t *node)
+{
+       dnode_t *n;
+       face_t  *f;
+       int             i;
+
+       if (node->planenum == PLANENUM_LEAF)
+       {
+               EmitLeaf (node);
+               return -numleafs;
+       }
+
+       // emit a node  
+       if (numnodes == MAX_MAP_NODES)
+               Error ("MAX_MAP_NODES");
+       n = &dnodes[numnodes];
+       numnodes++;
+
+       VectorCopy ((short) node->mins, n->mins);
+       VectorCopy ((short) node->maxs, n->maxs);
+
+       planeused[node->planenum]++;
+       planeused[node->planenum^1]++;
+
+       if (node->planenum & 1)
+               Error ("WriteDrawNodes_r: odd planenum");
+       n->planenum = node->planenum;
+       n->firstface = numfaces;
+
+       if (!node->faces)
+               c_nofaces++;
+       else
+               c_facenodes++;
+
+       for (f=node->faces ; f ; f=f->next)
+               EmitFace (f);
+
+       n->numfaces = numfaces - n->firstface;
+
+
+       //
+       // recursively output the other nodes
+       //      
+       for (i=0 ; i<2 ; i++)
+       {
+               if (node->children[i]->planenum == PLANENUM_LEAF)
+               {
+                       n->children[i] = -(numleafs + 1);
+                       EmitLeaf (node->children[i]);
+               }
+               else
+               {
+                       n->children[i] = numnodes;      
+                       EmitDrawNode_r (node->children[i]);
+               }
+       }
+
+       return n - dnodes;
+}
+
+//=========================================================
+
+
+/*
+============
+WriteBSP
+============
+*/
+void WriteBSP (node_t *headnode)
+{
+       int             oldfaces;
+
+       c_nofaces = 0;
+       c_facenodes = 0;
+
+       Sys_FPrintf( SYS_VRB, "--- WriteBSP ---\n");
+
+       oldfaces = numfaces;
+       dmodels[nummodels].headnode = EmitDrawNode_r (headnode);
+       EmitAreaPortals (headnode);
+
+       Sys_FPrintf( SYS_VRB, "%5i nodes with faces\n", c_facenodes);
+       Sys_FPrintf( SYS_VRB, "%5i nodes without faces\n", c_nofaces);
+       Sys_FPrintf( SYS_VRB, "%5i faces\n", numfaces-oldfaces);
+}
+
+//===========================================================
+
+/*
+============
+SetModelNumbers
+============
+*/
+void SetModelNumbers (void)
+{
+       int             i;
+       int             models;
+       char    value[10];
+
+       models = 1;
+       for (i=1 ; i<num_entities ; i++)
+       {
+               if (entities[i].numbrushes)
+               {
+                       sprintf (value, "*%i", models);
+                       models++;
+                       SetKeyValue (&entities[i], "model", value);
+               }
+       }
+
+}
+
+/*
+============
+SetLightStyles
+============
+*/
+#define        MAX_SWITCHED_LIGHTS     32
+void SetLightStyles (void)
+{
+       int             stylenum;
+       char    *t;
+       entity_t        *e;
+       int             i, j;
+       char    value[10];
+       char    lighttargets[MAX_SWITCHED_LIGHTS][64];
+
+
+       // any light that is controlled (has a targetname)
+       // must have a unique style number generated for it
+
+       stylenum = 0;
+       for (i=1 ; i<num_entities ; i++)
+       {
+               e = &entities[i];
+
+               t = ValueForKey (e, "classname");
+               if (Q_strncasecmp (t, "light", 5))
+                       continue;
+               t = ValueForKey (e, "targetname");
+               if (!t[0])
+                       continue;
+               
+               // find this targetname
+               for (j=0 ; j<stylenum ; j++)
+                       if (!strcmp (lighttargets[j], t))
+                               break;
+               if (j == stylenum)
+               {
+                       if (stylenum == MAX_SWITCHED_LIGHTS)
+                               Error ("stylenum == MAX_SWITCHED_LIGHTS");
+                       strcpy (lighttargets[j], t);
+                       stylenum++;
+               }
+               sprintf (value, "%i", 32 + j);
+               SetKeyValue (e, "style", value);
+       }
+
+}
+
+//===========================================================
+
+/*
+============
+EmitBrushes
+============
+*/
+void EmitBrushes (void)
+{
+       int                     i, j, bnum, s, x;
+       dbrush_t        *db;
+       mapbrush_t              *b;
+       dbrushside_t    *cp;
+       vec3_t          normal;
+       vec_t           dist;
+       int                     planenum;
+
+       numbrushsides = 0;
+       numbrushes = nummapbrushes;
+
+       for (bnum=0 ; bnum<nummapbrushes ; bnum++)
+       {
+               b = &mapbrushes[bnum];
+               db = &dbrushes[bnum];
+
+               db->contents = b->contents;
+               db->firstside = numbrushsides;
+               db->numsides = b->numsides;
+               for (j=0 ; j<b->numsides ; j++)
+               {
+                       if (numbrushsides == MAX_MAP_BRUSHSIDES)
+                               Error ("MAX_MAP_BRUSHSIDES");
+                       cp = &dbrushsides[numbrushsides];
+                       numbrushsides++;
+                       cp->planenum = b->original_sides[j].planenum;
+                       cp->texinfo = b->original_sides[j].texinfo;
+               }
+
+               // add any axis planes not contained in the brush to bevel off corners
+               for (x=0 ; x<3 ; x++)
+                       for (s=-1 ; s<=1 ; s+=2)
+                       {
+                       // add the plane
+                               VectorCopy (vec3_origin, normal);
+                               normal[x] = (float) s;
+                               if (s == -1)
+                                       dist = -b->mins[x];
+                               else
+                                       dist = b->maxs[x];
+                               planenum = FindFloatPlane (normal, dist);
+                               for (i=0 ; i<b->numsides ; i++)
+                                       if (b->original_sides[i].planenum == planenum)
+                                               break;
+                               if (i == b->numsides)
+                               {
+                                       if (numbrushsides >= MAX_MAP_BRUSHSIDES)
+                                               Error ("MAX_MAP_BRUSHSIDES");
+
+                                       dbrushsides[numbrushsides].planenum = planenum;
+                                       dbrushsides[numbrushsides].texinfo =
+                                               dbrushsides[numbrushsides-1].texinfo;
+                                       numbrushsides++;
+                                       db->numsides++;
+                               }
+                       }
+
+       }
+
+}
+
+//===========================================================
+
+/*
+==================
+BeginBSPFile
+==================
+*/
+void BeginBSPFile (void)
+{
+       // these values may actually be initialized
+       // if the file existed when loaded, so clear them explicitly
+       nummodels = 0;
+       numfaces = 0;
+       numnodes = 0;
+       numbrushsides = 0;
+       numvertexes = 0;
+       numleaffaces = 0;
+       numleafbrushes = 0;
+       numsurfedges = 0;
+
+       // edge 0 is not used, because 0 can't be negated
+       numedges = 1;
+
+       // leave vertex 0 as an error
+       numvertexes = 1;
+
+       // leave leaf 0 as an error
+       numleafs = 1;
+       dleafs[0].contents = CONTENTS_SOLID;
+}
+
+
+/*
+============
+EndBSPFile
+============
+*/
+void EndBSPFile (void)
+{
+       char    path[1024];
+
+#if 0
+       int             len;
+       byte    *buf;
+#endif
+
+       EmitBrushes ();
+       EmitPlanes ();
+       UnparseEntities ();
+
+       // load the pop
+#if 0
+       sprintf (path, "%s/pics/pop.lmp", gamedir);
+       len = LoadFile (path, &buf);
+       memcpy (dpop, buf, sizeof(dpop));
+       free (buf);
+#endif
+
+       // write the map
+       sprintf (path, "%s.bsp", source);
+       Sys_Printf ("Writing %s\n", path);
+       WriteBSPFile (path);
+}
+
+
+/*
+==================
+BeginModel
+==================
+*/
+int    firstmodleaf;
+extern int firstmodeledge;
+extern int     firstmodelface;
+void BeginModel (void)
+{
+       dmodel_t        *mod;
+       int                     start, end;
+       mapbrush_t      *b;
+       int                     j;
+       entity_t        *e;
+       vec3_t          mins, maxs;
+
+       if (nummodels == MAX_MAP_MODELS)
+               Error ("MAX_MAP_MODELS");
+       mod = &dmodels[nummodels];
+
+       mod->firstface = numfaces;
+
+       firstmodleaf = numleafs;
+       firstmodeledge = numedges;
+       firstmodelface = numfaces;
+
+       //
+       // bound the brushes
+       //
+       e = &entities[entity_num];
+
+       start = e->firstbrush;
+       end = start + e->numbrushes;
+       ClearBounds (mins, maxs);
+
+       for (j=start ; j<end ; j++)
+       {
+               b = &mapbrushes[j];
+               if (!b->numsides)
+                       continue;       // not a real brush (origin brush)
+               AddPointToBounds (b->mins, mins, maxs);
+               AddPointToBounds (b->maxs, mins, maxs);
+       }
+
+       VectorCopy (mins, mod->mins);
+       VectorCopy (maxs, mod->maxs);
+}
+
+
+/*
+==================
+EndModel
+==================
+*/
+void EndModel (void)
+{
+       dmodel_t        *mod;
+
+       mod = &dmodels[nummodels];
+
+       mod->numfaces = numfaces - mod->firstface;
+
+       nummodels++;
+}
+