aboutsummaryrefslogtreecommitdiffstats
path: root/code/bspc/map_q3.c
diff options
context:
space:
mode:
Diffstat (limited to 'code/bspc/map_q3.c')
-rwxr-xr-xcode/bspc/map_q3.c681
1 files changed, 681 insertions, 0 deletions
diff --git a/code/bspc/map_q3.c b/code/bspc/map_q3.c
new file mode 100755
index 0000000..750b304
--- /dev/null
+++ b/code/bspc/map_q3.c
@@ -0,0 +1,681 @@
+/*
+===========================================================================
+Copyright (C) 1999-2005 Id Software, Inc.
+
+This file is part of Quake III Arena source code.
+
+Quake III Arena source code 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.
+
+Quake III Arena source code 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 Foobar; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+===========================================================================
+*/
+
+#include "qbsp.h"
+#include "l_mem.h"
+#include "../botlib/aasfile.h" //aas_bbox_t
+#include "aas_store.h" //AAS_MAX_BBOXES
+#include "aas_cfg.h"
+#include "aas_map.h" //AAS_CreateMapBrushes
+#include "l_bsp_q3.h"
+#include "../qcommon/cm_patch.h"
+#include "../game/surfaceflags.h"
+
+#define NODESTACKSIZE 1024
+
+//===========================================================================
+//
+// Parameter: -
+// Returns: -
+// Changes Globals: -
+//===========================================================================
+void PrintContents(int contents);
+
+int Q3_BrushContents(mapbrush_t *b)
+{
+ int contents, i, mixed, hint;
+ side_t *s;
+
+ s = &b->original_sides[0];
+ contents = s->contents;
+ //
+ mixed = false;
+ hint = false;
+ for (i = 1; i < b->numsides; i++)
+ {
+ s = &b->original_sides[i];
+ if (s->contents != contents) mixed = true;
+ if (s->surf & (SURF_HINT|SURF_SKIP)) hint = true;
+ contents |= s->contents;
+ } //end for
+ //
+ if (hint)
+ {
+ if (contents)
+ {
+ Log_Write("WARNING: hint brush with contents: ");
+ PrintContents(contents);
+ Log_Write("\r\n");
+ //
+ Log_Write("brush contents is: ");
+ PrintContents(b->contents);
+ Log_Write("\r\n");
+ } //end if
+ return 0;
+ } //end if
+ //Log_Write("brush %d contents ", nummapbrushes);
+ //PrintContents(contents);
+ //Log_Write("\r\n");
+ //remove ladder and fog contents
+ contents &= ~(CONTENTS_LADDER|CONTENTS_FOG);
+ //
+ if (mixed)
+ {
+ Log_Write("Entity %i, Brush %i: mixed face contents "
+ , b->entitynum, b->brushnum);
+ PrintContents(contents);
+ Log_Write("\r\n");
+ //
+ Log_Write("brush contents is: ");
+ PrintContents(b->contents);
+ Log_Write("\r\n");
+ //
+ if (contents & CONTENTS_DONOTENTER) return CONTENTS_DONOTENTER;//Log_Print("mixed contents with donotenter\n");
+ /*
+ Log_Print("contents:"); PrintContents(contents);
+ Log_Print("\ncontents:"); PrintContents(s->contents);
+ Log_Print("\n");
+ Log_Print("texture name = %s\n", texinfo[s->texinfo].texture);
+ */
+ //if liquid brush
+ if (contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER))
+ {
+ return (contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER));
+ } //end if
+ if (contents & CONTENTS_PLAYERCLIP) return (contents & CONTENTS_PLAYERCLIP);
+ return (contents & CONTENTS_SOLID);
+ } //end if
+ /*
+ if (contents & CONTENTS_AREAPORTAL)
+ {
+ static int num;
+ Log_Write("Entity %i, Brush %i: area portal %d\r\n", b->entitynum, b->brushnum, num++);
+ } //end if*/
+ if (contents == (contents & CONTENTS_STRUCTURAL))
+ {
+ //Log_Print("brush %i is only structural\n", b->brushnum);
+ contents = 0;
+ } //end if
+ if (contents & CONTENTS_DONOTENTER)
+ {
+ Log_Print("brush %i is a donotenter brush, c = %X\n", b->brushnum, contents);
+ } //end if
+ return contents;
+} //end of the function Q3_BrushContents
+#define BBOX_NORMAL_EPSILON 0.0001
+//===========================================================================
+//
+// Parameter: -
+// Returns: -
+// Changes Globals: -
+//===========================================================================
+void Q3_DPlanes2MapPlanes(void)
+{
+ int i;
+
+ for (i = 0; i < q3_numplanes; i++)
+ {
+ dplanes2mapplanes[i] = FindFloatPlane(q3_dplanes[i].normal, q3_dplanes[i].dist);
+ } //end for
+} //end of the function Q3_DPlanes2MapPlanes
+//===========================================================================
+//
+// Parameter: -
+// Returns: -
+// Changes Globals: -
+//===========================================================================
+void Q3_BSPBrushToMapBrush(q3_dbrush_t *bspbrush, entity_t *mapent)
+{
+ mapbrush_t *b;
+ int i, k, n;
+ side_t *side, *s2;
+ int planenum;
+ q3_dbrushside_t *bspbrushside;
+ q3_dplane_t *bspplane;
+
+ if (nummapbrushes >= MAX_MAPFILE_BRUSHES)
+ Error ("nummapbrushes >= MAX_MAPFILE_BRUSHES");
+
+ b = &mapbrushes[nummapbrushes];
+ b->original_sides = &brushsides[nummapbrushsides];
+ b->entitynum = mapent-entities;
+ b->brushnum = nummapbrushes - mapent->firstbrush;
+ b->leafnum = dbrushleafnums[bspbrush - q3_dbrushes];
+
+ for (n = 0; n < bspbrush->numSides; n++)
+ {
+ //pointer to the bsp brush side
+ bspbrushside = &q3_dbrushsides[bspbrush->firstSide + n];
+
+ if (nummapbrushsides >= MAX_MAPFILE_BRUSHSIDES)
+ {
+ Error ("MAX_MAPFILE_BRUSHSIDES");
+ } //end if
+ //pointer to the map brush side
+ side = &brushsides[nummapbrushsides];
+ //if the BSP brush side is textured
+ if (q3_dbrushsidetextured[bspbrush->firstSide + n]) side->flags |= SFL_TEXTURED|SFL_VISIBLE;
+ else side->flags &= ~SFL_TEXTURED;
+ //NOTE: all Quake3 sides are assumed textured
+ //side->flags |= SFL_TEXTURED|SFL_VISIBLE;
+ //
+ if (bspbrushside->shaderNum < 0)
+ {
+ side->contents = 0;
+ side->surf = 0;
+ } //end if
+ else
+ {
+ side->contents = q3_dshaders[bspbrushside->shaderNum].contentFlags;
+ side->surf = q3_dshaders[bspbrushside->shaderNum].surfaceFlags;
+ if (strstr(q3_dshaders[bspbrushside->shaderNum].shader, "common/hint"))
+ {
+ //Log_Print("found hint side\n");
+ side->surf |= SURF_HINT;
+ } //end if
+ } //end else
+ //
+ if (side->surf & SURF_NODRAW)
+ {
+ side->flags |= SFL_TEXTURED|SFL_VISIBLE;
+ } //end if
+ /*
+ if (side->contents & (CONTENTS_TRANSLUCENT|CONTENTS_STRUCTURAL))
+ {
+ side->flags |= SFL_TEXTURED|SFL_VISIBLE;
+ } //end if*/
+
+ // hints and skips are never detail, and have no content
+ if (side->surf & (SURF_HINT|SURF_SKIP) )
+ {
+ side->contents = 0;
+ //Log_Print("found hint brush side\n");
+ }
+ /*
+ if ((side->surf & SURF_NODRAW) && (side->surf & SURF_NOIMPACT))
+ {
+ side->contents = 0;
+ side->surf &= ~CONTENTS_DETAIL;
+ Log_Print("probably found hint brush in a BSP without hints being used\n");
+ } //end if*/
+
+ //ME: get a plane for this side
+ bspplane = &q3_dplanes[bspbrushside->planeNum];
+ planenum = FindFloatPlane(bspplane->normal, bspplane->dist);
+ //
+ // see if the plane has been used already
+ //
+ //ME: this really shouldn't happen!!!
+ //ME: otherwise the bsp file is corrupted??
+ //ME: still it seems to happen, maybe Johny Boy's
+ //ME: brush bevel adding is crappy ?
+ for (k = 0; k < b->numsides; k++)
+ {
+ s2 = b->original_sides + k;
+// if (DotProduct (mapplanes[s2->planenum].normal, mapplanes[planenum].normal) > 0.999
+// && fabs(mapplanes[s2->planenum].dist - mapplanes[planenum].dist) < 0.01 )
+
+ if (s2->planenum == planenum)
+ {
+ Log_Print("Entity %i, Brush %i: duplicate plane\n"
+ , b->entitynum, b->brushnum);
+ break;
+ }
+ if ( s2->planenum == (planenum^1) )
+ {
+ Log_Print("Entity %i, Brush %i: mirrored plane\n"
+ , b->entitynum, b->brushnum);
+ break;
+ }
+ }
+ if (k != b->numsides)
+ continue; // duplicated
+
+ //
+ // keep this side
+ //
+ //ME: reset pointer to side, why? hell I dunno (pointer is set above already)
+ side = b->original_sides + b->numsides;
+ //ME: store the plane number
+ side->planenum = planenum;
+ //ME: texinfo is already stored when bsp is loaded
+ //NOTE: check for TEXINFO_NODE, otherwise crash in Q3_BrushContents
+ //if (bspbrushside->texinfo < 0) side->texinfo = 0;
+ //else side->texinfo = bspbrushside->texinfo;
+
+ // save the td off in case there is an origin brush and we
+ // have to recalculate the texinfo
+ // ME: don't need to recalculate because it's already done
+ // (for non-world entities) in the BSP file
+// side_brushtextures[nummapbrushsides] = td;
+
+ nummapbrushsides++;
+ b->numsides++;
+ } //end for
+
+ // get the content for the entire brush
+ b->contents = q3_dshaders[bspbrush->shaderNum].contentFlags;
+ b->contents &= ~(CONTENTS_LADDER|CONTENTS_FOG|CONTENTS_STRUCTURAL);
+// b->contents = Q3_BrushContents(b);
+ //
+
+ if (BrushExists(b))
+ {
+ c_squattbrushes++;
+ b->numsides = 0;
+ return;
+ } //end if
+
+ //if we're creating AAS
+ if (create_aas)
+ {
+ //create the AAS brushes from this brush, don't add brush bevels
+ AAS_CreateMapBrushes(b, mapent, false);
+ return;
+ } //end if
+
+ // allow detail brushes to be removed
+ if (nodetail && (b->contents & CONTENTS_DETAIL) )
+ {
+ b->numsides = 0;
+ return;
+ } //end if
+
+ // allow water brushes to be removed
+ if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
+ {
+ b->numsides = 0;
+ return;
+ } //end if
+
+ // create windings for sides and bounds for brush
+ MakeBrushWindings(b);
+
+ //mark brushes without winding or with a tiny window as bevels
+ MarkBrushBevels(b);
+
+ // brushes that will not be visible at all will never be
+ // used as bsp splitters
+ if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
+ {
+ c_clipbrushes++;
+ for (i = 0; i < b->numsides; i++)
+ b->original_sides[i].texinfo = TEXINFO_NODE;
+ } //end for
+
+ //
+ // origin brushes are removed, but they set
+ // the rotation origin for the rest of the brushes
+ // in the entity. After the entire entity is parsed,
+ // the planenums and texinfos will be adjusted for
+ // the origin brush
+ //
+ //ME: not needed because the entities in the BSP file already
+ // have an origin set
+// if (b->contents & CONTENTS_ORIGIN)
+// {
+// char string[32];
+// vec3_t origin;
+//
+// if (num_entities == 1)
+// {
+// Error ("Entity %i, Brush %i: origin brushes not allowed in world"
+// , b->entitynum, b->brushnum);
+// return;
+// }
+//
+// VectorAdd (b->mins, b->maxs, origin);
+// VectorScale (origin, 0.5, origin);
+//
+// sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
+// SetKeyValue (&entities[b->entitynum], "origin", string);
+//
+// VectorCopy (origin, entities[b->entitynum].origin);
+//
+// // don't keep this brush
+// b->numsides = 0;
+//
+// return;
+// }
+
+ //ME: the bsp brushes already have bevels, so we won't try to
+ // add them again (especially since Johny Boy's bevel adding might
+ // be crappy)
+// AddBrushBevels(b);
+
+ nummapbrushes++;
+ mapent->numbrushes++;
+} //end of the function Q3_BSPBrushToMapBrush
+//===========================================================================
+//
+// Parameter: -
+// Returns: -
+// Changes Globals: -
+//===========================================================================
+void Q3_ParseBSPBrushes(entity_t *mapent)
+{
+ int i;
+
+ for (i = 0; i < q3_dmodels[mapent->modelnum].numBrushes; i++)
+ {
+ Q3_BSPBrushToMapBrush(&q3_dbrushes[q3_dmodels[mapent->modelnum].firstBrush + i], mapent);
+ } //end for
+} //end of the function Q3_ParseBSPBrushes
+//===========================================================================
+//
+// Parameter: -
+// Returns: -
+// Changes Globals: -
+//===========================================================================
+qboolean Q3_ParseBSPEntity(int entnum)
+{
+ entity_t *mapent;
+ char *model;
+ int startbrush, startsides;
+
+ startbrush = nummapbrushes;
+ startsides = nummapbrushsides;
+
+ mapent = &entities[entnum];//num_entities];
+ mapent->firstbrush = nummapbrushes;
+ mapent->numbrushes = 0;
+ mapent->modelnum = -1; //-1 = no BSP model
+
+ model = ValueForKey(mapent, "model");
+ if (model && strlen(model))
+ {
+ if (*model == '*')
+ {
+ //get the model number of this entity (skip the leading *)
+ mapent->modelnum = atoi(&model[1]);
+ } //end if
+ } //end if
+
+ GetVectorForKey(mapent, "origin", mapent->origin);
+
+ //if this is the world entity it has model number zero
+ //the world entity has no model key
+ if (!strcmp("worldspawn", ValueForKey(mapent, "classname")))
+ {
+ mapent->modelnum = 0;
+ } //end if
+ //if the map entity has a BSP model (a modelnum of -1 is used for
+ //entities that aren't using a BSP model)
+ if (mapent->modelnum >= 0)
+ {
+ //parse the bsp brushes
+ Q3_ParseBSPBrushes(mapent);
+ } //end if
+ //
+ //the origin of the entity is already taken into account
+ //
+ //func_group entities can't be in the bsp file
+ //
+ //check out the func_areaportal entities
+ if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
+ {
+ c_areaportals++;
+ mapent->areaportalnum = c_areaportals;
+ return true;
+ } //end if
+ return true;
+} //end of the function Q3_ParseBSPEntity
+//===========================================================================
+//
+// Parameter: -
+// Returns: -
+// Changes Globals: -
+//===========================================================================
+#define MAX_PATCH_VERTS 1024
+
+void AAS_CreateCurveBrushes(void)
+{
+ int i, j, n, planenum, numcurvebrushes = 0;
+ q3_dsurface_t *surface;
+ q3_drawVert_t *dv_p;
+ vec3_t points[MAX_PATCH_VERTS];
+ int width, height, c;
+ patchCollide_t *pc;
+ facet_t *facet;
+ mapbrush_t *brush;
+ side_t *side;
+ entity_t *mapent;
+ winding_t *winding;
+
+ qprintf("nummapbrushsides = %d\n", nummapbrushsides);
+ mapent = &entities[0];
+ for (i = 0; i < q3_numDrawSurfaces; i++)
+ {
+ surface = &q3_drawSurfaces[i];
+ if ( ! surface->patchWidth ) continue;
+ // if the curve is not solid
+ if (!(q3_dshaders[surface->shaderNum].contentFlags & (CONTENTS_SOLID|CONTENTS_PLAYERCLIP)))
+ {
+ //Log_Print("skipped non-solid curve\n");
+ continue;
+ } //end if
+ // if this curve should not be used for AAS
+ if ( q3_dshaders[surface->shaderNum].contentFlags & CONTENTS_NOBOTCLIP ) {
+ continue;
+ }
+ //
+ width = surface->patchWidth;
+ height = surface->patchHeight;
+ c = width * height;
+ if (c > MAX_PATCH_VERTS)
+ {
+ Error("ParseMesh: MAX_PATCH_VERTS");
+ } //end if
+
+ dv_p = q3_drawVerts + surface->firstVert;
+ for ( j = 0 ; j < c ; j++, dv_p++ )
+ {
+ points[j][0] = dv_p->xyz[0];
+ points[j][1] = dv_p->xyz[1];
+ points[j][2] = dv_p->xyz[2];
+ } //end for
+ // create the internal facet structure
+ pc = CM_GeneratePatchCollide(width, height, points);
+ //
+ for (j = 0; j < pc->numFacets; j++)
+ {
+ facet = &pc->facets[j];
+ //
+ brush = &mapbrushes[nummapbrushes];
+ brush->original_sides = &brushsides[nummapbrushsides];
+ brush->entitynum = 0;
+ brush->brushnum = nummapbrushes - mapent->firstbrush;
+ //
+ brush->numsides = facet->numBorders + 2;
+ nummapbrushsides += brush->numsides;
+ brush->contents = CONTENTS_SOLID;
+ //
+ //qprintf("\r%6d curve brushes", nummapbrushsides);//++numcurvebrushes);
+ qprintf("\r%6d curve brushes", ++numcurvebrushes);
+ //
+ planenum = FindFloatPlane(pc->planes[facet->surfacePlane].plane, pc->planes[facet->surfacePlane].plane[3]);
+ //
+ side = &brush->original_sides[0];
+ side->planenum = planenum;
+ side->contents = CONTENTS_SOLID;
+ side->flags |= SFL_TEXTURED|SFL_VISIBLE|SFL_CURVE;
+ side->surf = 0;
+ //
+ side = &brush->original_sides[1];
+ if (create_aas)
+ {
+ //the plane is expanded later so it's not a problem that
+ //these first two opposite sides are coplanar
+ side->planenum = planenum ^ 1;
+ } //end if
+ else
+ {
+ side->planenum = FindFloatPlane(mapplanes[planenum^1].normal, mapplanes[planenum^1].dist + 1);
+ side->flags |= SFL_TEXTURED|SFL_VISIBLE;
+ } //end else
+ side->contents = CONTENTS_SOLID;
+ side->flags |= SFL_CURVE;
+ side->surf = 0;
+ //
+ winding = BaseWindingForPlane(mapplanes[side->planenum].normal, mapplanes[side->planenum].dist);
+ for (n = 0; n < facet->numBorders; n++)
+ {
+ //never use the surface plane as a border
+ if (facet->borderPlanes[n] == facet->surfacePlane) continue;
+ //
+ side = &brush->original_sides[2 + n];
+ side->planenum = FindFloatPlane(pc->planes[facet->borderPlanes[n]].plane, pc->planes[facet->borderPlanes[n]].plane[3]);
+ if (facet->borderInward[n]) side->planenum ^= 1;
+ side->contents = CONTENTS_SOLID;
+ side->flags |= SFL_TEXTURED|SFL_CURVE;
+ side->surf = 0;
+ //chop the winding in place
+ if (winding) ChopWindingInPlace(&winding, mapplanes[side->planenum^1].normal, mapplanes[side->planenum^1].dist, 0.1); //CLIP_EPSILON);
+ } //end for
+ //VectorCopy(pc->bounds[0], brush->mins);
+ //VectorCopy(pc->bounds[1], brush->maxs);
+ if (!winding)
+ {
+ Log_Print("WARNING: AAS_CreateCurveBrushes: no winding\n");
+ brush->numsides = 0;
+ continue;
+ } //end if
+ brush->original_sides[0].winding = winding;
+ WindingBounds(winding, brush->mins, brush->maxs);
+ for (n = 0; n < 3; n++)
+ {
+ //IDBUG: all the indexes into the mins and maxs were zero (not using i)
+ if (brush->mins[n] < -MAX_MAP_BOUNDS || brush->maxs[n] > MAX_MAP_BOUNDS)
+ {
+ Log_Print("entity %i, brush %i: bounds out of range\n", brush->entitynum, brush->brushnum);
+ Log_Print("brush->mins[%d] = %f, brush->maxs[%d] = %f\n", n, brush->mins[n], n, brush->maxs[n]);
+ brush->numsides = 0; //remove the brush
+ break;
+ } //end if
+ if (brush->mins[n] > MAX_MAP_BOUNDS || brush->maxs[n] < -MAX_MAP_BOUNDS)
+ {
+ Log_Print("entity %i, brush %i: no visible sides on brush\n", brush->entitynum, brush->brushnum);
+ Log_Print("brush->mins[%d] = %f, brush->maxs[%d] = %f\n", n, brush->mins[n], n, brush->maxs[n]);
+ brush->numsides = 0; //remove the brush
+ break;
+ } //end if
+ } //end for
+ if (create_aas)
+ {
+ //NOTE: brush bevels now already added
+ //AddBrushBevels(brush);
+ AAS_CreateMapBrushes(brush, mapent, false);
+ } //end if
+ else
+ {
+ // create windings for sides and bounds for brush
+ MakeBrushWindings(brush);
+ AddBrushBevels(brush);
+ nummapbrushes++;
+ mapent->numbrushes++;
+ } //end else
+ } //end for
+ } //end for
+ //qprintf("\r%6d curve brushes", nummapbrushsides);//++numcurvebrushes);
+ qprintf("\r%6d curve brushes\n", numcurvebrushes);
+} //end of the function AAS_CreateCurveBrushes
+//===========================================================================
+//
+// Parameter: -
+// Returns: -
+// Changes Globals: -
+//===========================================================================
+void AAS_ExpandMapBrush(mapbrush_t *brush, vec3_t mins, vec3_t maxs);
+
+void Q3_LoadMapFromBSP(struct quakefile_s *qf)
+{
+ int i;
+ vec3_t mins = {-1,-1,-1}, maxs = {1, 1, 1};
+
+ Log_Print("-- Q3_LoadMapFromBSP --\n");
+ //loaded map type
+ loadedmaptype = MAPTYPE_QUAKE3;
+
+ Log_Print("Loading map from %s...\n", qf->filename);
+ //load the bsp file
+ Q3_LoadBSPFile(qf);
+
+ //create an index from bsp planes to map planes
+ //DPlanes2MapPlanes();
+ //clear brush model numbers
+ for (i = 0; i < MAX_MAPFILE_BRUSHES; i++)
+ brushmodelnumbers[i] = -1;
+
+ nummapbrushsides = 0;
+ num_entities = 0;
+
+ Q3_ParseEntities();
+ //
+ for (i = 0; i < num_entities; i++)
+ {
+ Q3_ParseBSPEntity(i);
+ } //end for
+
+ AAS_CreateCurveBrushes();
+ //get the map mins and maxs from the world model
+ ClearBounds(map_mins, map_maxs);
+ for (i = 0; i < entities[0].numbrushes; i++)
+ {
+ if (mapbrushes[i].numsides <= 0)
+ continue;
+ AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
+ AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
+ } //end for
+ /*/
+ for (i = 0; i < nummapbrushes; i++)
+ {
+ //if (!mapbrushes[i].original_sides) continue;
+ //AddBrushBevels(&mapbrushes[i]);
+ //AAS_ExpandMapBrush(&mapbrushes[i], mins, maxs);
+ } //end for*/
+ /*
+ for (i = 0; i < nummapbrushsides; i++)
+ {
+ Log_Write("side %d flags = %d", i, brushsides[i].flags);
+ } //end for
+ for (i = 0; i < nummapbrushes; i++)
+ {
+ Log_Write("brush contents: ");
+ PrintContents(mapbrushes[i].contents);
+ Log_Print("\n");
+ } //end for*/
+} //end of the function Q3_LoadMapFromBSP
+//===========================================================================
+//
+// Parameter: -
+// Returns: -
+// Changes Globals: -
+//===========================================================================
+void Q3_ResetMapLoading(void)
+{
+ //reset for map loading from bsp
+ memset(nodestack, 0, NODESTACKSIZE * sizeof(int));
+ nodestackptr = NULL;
+ nodestacksize = 0;
+ memset(brushmodelnumbers, 0, MAX_MAPFILE_BRUSHES * sizeof(int));
+} //end of the function Q3_ResetMapLoading
+