-/*\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++;
+}