writebsp.c

Go to the documentation of this file.
00001 
00005 /*
00006 Copyright (C) 1997-2001 Id Software, Inc.
00007 
00008 This program is free software; you can redistribute it and/or
00009 modify it under the terms of the GNU General Public License
00010 as published by the Free Software Foundation; either version 2
00011 of the License, or (at your option) any later version.
00012 
00013 This program is distributed in the hope that it will be useful,
00014 but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016 
00017 See the GNU General Public License for more details.
00018 
00019 You should have received a copy of the GNU General Public License
00020 along with this program; if not, write to the Free Software
00021 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00022 
00023 */
00024 
00025 #include "bsp.h"
00026 
00027 static int c_nofaces;
00028 static int c_facenodes;
00029 
00030 /*
00031 =========================================================
00032 ONLY SAVE OUT PLANES THAT ARE ACTUALLY USED AS NODES
00033 =========================================================
00034 */
00035 
00041 void EmitPlanes (void)
00042 {
00043     int i;
00044     const plane_t *mp = mapplanes;
00045 
00046     for (i = 0; i < nummapplanes; i++, mp++) {
00047         dBspPlane_t *dp = &curTile->planes[curTile->numplanes];
00048         VectorCopy(mp->normal, dp->normal);
00049         dp->dist = mp->dist;
00050         dp->type = mp->type;
00051         curTile->numplanes++;
00052     }
00053 }
00054 
00058 static void EmitLeaf (const node_t *node)
00059 {
00060     dBspLeaf_t *leaf_p;
00061     int i, brushnum;
00062     const bspbrush_t *b;
00063 
00064     /* emit a leaf */
00065     if (curTile->numleafs >= MAX_MAP_LEAFS)
00066         Sys_Error("MAX_MAP_LEAFS (%i)", curTile->numleafs);
00067 
00068     leaf_p = &curTile->leafs[curTile->numleafs];
00069     curTile->numleafs++;
00070 
00071     leaf_p->contentFlags = node->contentFlags;
00072     leaf_p->area = node->area;
00073 
00074     /* write bounding box info */
00075     VectorCopy((short)node->mins, leaf_p->mins);
00076     VectorCopy((short)node->maxs, leaf_p->maxs);
00077 
00078     /* write the leafbrushes */
00079     leaf_p->firstleafbrush = curTile->numleafbrushes;
00080     for (b = node->brushlist; b; b = b->next) {
00081         if (curTile->numleafbrushes >= MAX_MAP_LEAFBRUSHES)
00082             Sys_Error("MAX_MAP_LEAFBRUSHES (%i)", curTile->numleafbrushes);
00083 
00084         brushnum = b->original - mapbrushes;
00085         for (i = leaf_p->firstleafbrush; i < curTile->numleafbrushes; i++)
00086             if (curTile->leafbrushes[i] == brushnum)
00087                 break;
00088         if (i == curTile->numleafbrushes) {
00089             Verb_Printf(VERB_DUMP, "EmitLeaf: adding brush %i to leaf %i\n", brushnum, curTile->numleafs - 1);
00090             curTile->leafbrushes[curTile->numleafbrushes] = brushnum;
00091             curTile->numleafbrushes++;
00092         }
00093     }
00094     leaf_p->numleafbrushes = curTile->numleafbrushes - leaf_p->firstleafbrush;
00095 }
00096 
00097 
00102 static void EmitFace (const face_t *f)
00103 {
00104     dBspSurface_t *df;
00105     int i;
00106 
00107     if (f->numpoints < 3) {
00108         return;     /* degenerated */
00109     }
00110     if (f->merged || f->split[0] || f->split[1]) {
00111         return;     /* not a final face */
00112     }
00113 
00114     if (curTile->numfaces >= MAX_MAP_FACES)
00115         Sys_Error("numfaces >= MAX_MAP_FACES (%i)", curTile->numfaces);
00116     df = &curTile->faces[curTile->numfaces];
00117     curTile->numfaces++;
00118 
00119     /* planenum is used in lighting stage, but not in ufo */
00120     df->planenum = f->planenum & (~1);
00121     df->side = f->planenum & 1;
00122 
00123     df->firstedge = curTile->numsurfedges;
00124     df->numedges = f->numpoints;
00125     df->texinfo = f->texinfo;
00126     for (i = 0; i < f->numpoints; i++) {
00127         const int e = GetEdge(f->vertexnums[i], f->vertexnums[(i + 1) % f->numpoints], f);
00128         if (curTile->numsurfedges >= MAX_MAP_SURFEDGES)
00129             Sys_Error("numsurfedges >= MAX_MAP_SURFEDGES (%i)", curTile->numsurfedges);
00130         curTile->surfedges[curTile->numsurfedges] = e;
00131         curTile->numsurfedges++;
00132     }
00133     for (i = 0; i < LIGHTMAP_MAX; i++)
00134         df->lightofs[i] = -1;
00135 }
00136 
00141 static int EmitDrawNode_r (node_t *node)
00142 {
00143     const char* side[2] = {"front", "back"};
00144     dBspNode_t *n;
00145     const face_t *f;
00146     int i;
00147 
00148     if (node->planenum == PLANENUM_LEAF) {
00149         Verb_Printf(VERB_DUMP, "EmitDrawNode_r: creating singleton leaf.\n");
00150         EmitLeaf(node);
00151         return -curTile->numleafs;
00152     }
00153 
00154     /* emit a node   */
00155     if (curTile->numnodes >= MAX_MAP_NODES)
00156         Sys_Error("MAX_MAP_NODES (%i)", curTile->numnodes);
00157     n = &curTile->nodes[curTile->numnodes];
00158     Verb_Printf(VERB_DUMP, "EmitDrawNode_r: creating bsp node %i\n", curTile->numnodes);
00159     curTile->numnodes++;
00160 
00161     VectorCopy((short)node->mins, n->mins);
00162     VectorCopy((short)node->maxs, n->maxs);
00163 
00164     if (node->planenum & 1)
00165         Sys_Error("EmitDrawNode_r: odd planenum: %i", node->planenum);
00166     n->planenum = node->planenum;
00167     n->firstface = curTile->numfaces;
00168 
00169     if (!node->faces)
00170         c_nofaces++;
00171     else
00172         c_facenodes++;
00173 
00174     for (f = node->faces; f; f = f->next)
00175         EmitFace(f);
00176 
00177     n->numfaces = curTile->numfaces - n->firstface;
00178 
00179     /* recursively output the other nodes */
00180     for (i = 0; i < 2; i++) {
00181         if (node->children[i]->planenum == PLANENUM_LEAF) {
00182             Verb_Printf(VERB_DUMP, "EmitDrawNode_r: creating child leaf for %s of bsp node "UFO_SIZE_T".\n", side[i], n - curTile->nodes);
00183             n->children[i] = -(curTile->numleafs + 1);
00184             EmitLeaf(node->children[i]);
00185         } else {
00186             Verb_Printf(VERB_DUMP, "EmitDrawNode_r: adding child node for bsp node "UFO_SIZE_T".\n", n - curTile->nodes);
00187             n->children[i] = curTile->numnodes;
00188             EmitDrawNode_r(node->children[i]);
00189         }
00190     }
00191 
00192     return n - curTile->nodes;
00193 }
00194 
00195 
00201 int WriteBSP (node_t *headnode)
00202 {
00203     int oldfaces, emittedHeadnode;
00204 
00205     c_nofaces = 0;
00206     c_facenodes = 0;
00207 
00208     Verb_Printf(VERB_EXTRA, "--- WriteBSP ---\n");
00209 
00210     oldfaces = curTile->numfaces;
00211     emittedHeadnode = EmitDrawNode_r(headnode);
00212 
00213     Verb_Printf(VERB_EXTRA, "%5i nodes with faces\n", c_facenodes);
00214     Verb_Printf(VERB_EXTRA, "%5i nodes without faces\n", c_nofaces);
00215     Verb_Printf(VERB_EXTRA, "%5i faces\n", curTile->numfaces - oldfaces);
00216 
00217     return emittedHeadnode;
00218 }
00219 
00223 void SetModelNumbers (void)
00224 {
00225     int i;
00226     char value[10];
00227 
00228     /* 0 is the world - start at 1 */
00229     int models = 1;
00230     for (i = 1; i < num_entities; i++) {
00231         if (entities[i].numbrushes) {
00232             Com_sprintf(value, sizeof(value), "*%i", models);
00233             models++;
00234             SetKeyValue(&entities[i], "model", value);
00235         }
00236     }
00237 }
00238 
00242 void EmitBrushes (void)
00243 {
00244     int i, j, bnum, s, x;
00245     vec3_t normal;
00246     vec_t dist;
00247     int planenum;
00248 
00249     curTile->numbrushsides = 0;
00250     curTile->numbrushes = nummapbrushes;
00251     /* Clear out curTile->brushes */
00252     memset(curTile->brushes, 0, MAX_MAP_BRUSHES * sizeof(cBspBrush_t));
00253 
00254     for (bnum = 0; bnum < nummapbrushes; bnum++) {
00255         const mapbrush_t *b = &mapbrushes[bnum];
00256         dBspBrush_t *db = &curTile->dbrushes[bnum];
00257         cBspBrush_t *cb = &curTile->brushes[bnum];
00258 
00259         db->contentFlags = b->contentFlags;
00260         db->firstbrushside = curTile->numbrushsides;
00261         db->numsides = b->numsides;
00262         cb->contentFlags = b->contentFlags;
00263         cb->firstbrushside = curTile->numbrushsides;
00264         cb->numsides = b->numsides;
00265         cb->checkcount = 0;
00266         for (j = 0; j < b->numsides; j++) {
00267             if (curTile->numbrushsides == MAX_MAP_BRUSHSIDES) {
00268                 Sys_Error("MAX_MAP_BRUSHSIDES (%i)", curTile->numbrushsides);
00269             } else {
00270                 dBspBrushSide_t *cp = &curTile->brushsides[curTile->numbrushsides];
00271                 curTile->numbrushsides++;
00272                 cp->planenum = b->original_sides[j].planenum;
00273                 cp->texinfo = b->original_sides[j].texinfo;
00274             }
00275         }
00276 
00277         /* add any axis planes not contained in the brush to bevel off corners */
00278         for (x = 0; x < 3; x++)
00279             for (s = -1; s <= 1; s += 2) {
00280                 /* add the plane */
00281                 VectorCopy(vec3_origin, normal);
00282                 normal[x] = (float)s;
00283                 if (s == -1)
00284                     dist = -b->mins[x];
00285                 else
00286                     dist = b->maxs[x];
00287                 planenum = FindOrCreateFloatPlane(normal, dist);
00288                 for (i = 0; i < b->numsides; i++)
00289                     if (b->original_sides[i].planenum == planenum)
00290                         break;
00291                 if (i == b->numsides) {
00292                     if (curTile->numbrushsides >= MAX_MAP_BRUSHSIDES)
00293                         Sys_Error("MAX_MAP_BRUSHSIDES (%i)", curTile->numbrushsides);
00294 
00295                     curTile->brushsides[curTile->numbrushsides].planenum = planenum;
00296                     curTile->brushsides[curTile->numbrushsides].texinfo = curTile->brushsides[curTile->numbrushsides - 1].texinfo;
00297                     curTile->numbrushsides++;
00298                     db->numsides++;
00299                     cb->numsides++;
00300                 }
00301             }
00302     }
00303 }
00304 
00309 void BeginBSPFile (void)
00310 {
00311     /* Create this shortcut to mapTiles[0] */
00312     curTile = &mapTiles.mapTiles[0];
00313     /* Set the number of tiles to 1. */
00314     mapTiles.numTiles = 1;
00315 
00316     /* these values may actually be initialized
00317      * if the file existed when loaded, so clear them explicitly */
00318     curTile->nummodels = 0;
00319     curTile->numfaces = 0;
00320     curTile->numbrushsides = 0;
00321     curTile->numleafbrushes = 0;
00322     curTile->numsurfedges = 0;
00323     curTile->numnodes = 0;
00324 
00325     /* edge 0 is not used, because 0 can't be negated */
00326     curTile->numedges = 1;
00327 
00328     /* leave vertex 0 as an error */
00329     curTile->numvertexes = 1;
00330     curTile->numnormals = 1;
00331 
00332     /* leave leaf 0 as an error */
00333     curTile->numleafs = 1;
00334     curTile->leafs[0].contentFlags = CONTENTS_SOLID;
00335 }
00336 
00337 
00342 void EndBSPFile (const char *filename)
00343 {
00344     EmitBrushes();
00345     EmitPlanes();
00346     UnparseEntities();
00347 
00348     /* write the map */
00349     Verb_Printf(VERB_LESS, "Writing %s\n", filename);
00350     WriteBSPFile(filename);
00351 }
00352 
00353 extern int firstmodeledge;
00354 
00359 void BeginModel (int entityNum)
00360 {
00361     dBspModel_t *mod;
00362     int start, end;
00363     int j;
00364     const entity_t *e;
00365     vec3_t mins, maxs;
00366 
00367     if (curTile->nummodels == MAX_MAP_MODELS)
00368         Sys_Error("MAX_MAP_MODELS (%i)", curTile->nummodels);
00369     mod = &curTile->models[curTile->nummodels];
00370 
00371     mod->firstface = curTile->numfaces;
00372 
00373     firstmodeledge = curTile->numedges;
00374 
00375     /* bound the brushes */
00376     e = &entities[entityNum];
00377 
00378     start = e->firstbrush;
00379     end = start + e->numbrushes;
00380     ClearBounds(mins, maxs);
00381 
00382     for (j = start; j < end; j++) {
00383         mapbrush_t *b = &mapbrushes[j];
00384         /* not a real brush (origin brush) - e.g. func_door */
00385         if (!b->numsides)
00386             continue;
00387         AddPointToBounds(b->mins, mins, maxs);
00388         AddPointToBounds(b->maxs, mins, maxs);
00389     }
00390 
00391     VectorCopy(mins, mod->mins);
00392     VectorCopy(maxs, mod->maxs);
00393 }
00394 
00395 
00400 void EndModel (void)
00401 {
00402     dBspModel_t *mod;
00403 
00404     /* set surfaces and brushes */
00405     mod = &curTile->models[curTile->nummodels];
00406     mod->numfaces = curTile->numfaces - mod->firstface;
00407 
00408     /* increment model count */
00409     curTile->nummodels++;
00410 }

Generated by  doxygen 1.6.2