1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018 |
- /*
- ===========================================================================
- Copyright (C) 1997-2006 Id Software, Inc.
- This file is part of Quake 2 Tools source code.
- Quake 2 Tools 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 2 Tools 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 Quake 2 Tools source code; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- ===========================================================================
- */
- #include "qbsp.h"
- extern qboolean onlyents;
- int nummapbrushes;
- mapbrush_t mapbrushes[MAX_MAP_BRUSHES];
- int nummapbrushsides;
- side_t brushsides[MAX_MAP_SIDES];
- brush_texture_t side_brushtextures[MAX_MAP_SIDES];
- int nummapplanes;
- plane_t mapplanes[MAX_MAP_PLANES];
- #define PLANE_HASHES 1024
- plane_t *planehash[PLANE_HASHES];
- vec3_t map_mins, map_maxs;
- // undefine to make plane finding use linear sort
- #define USE_HASHING
- void TestExpandBrushes (void);
- int c_boxbevels;
- int c_edgebevels;
- int c_areaportals;
- int c_clipbrushes;
- /*
- =============================================================================
- PLANE FINDING
- =============================================================================
- */
- /*
- =================
- PlaneTypeForNormal
- =================
- */
- int PlaneTypeForNormal (vec3_t normal)
- {
- vec_t ax, ay, az;
-
- // NOTE: should these have an epsilon around 1.0?
- if (normal[0] == 1.0 || normal[0] == -1.0)
- return PLANE_X;
- if (normal[1] == 1.0 || normal[1] == -1.0)
- return PLANE_Y;
- if (normal[2] == 1.0 || normal[2] == -1.0)
- return PLANE_Z;
-
- ax = fabs(normal[0]);
- ay = fabs(normal[1]);
- az = fabs(normal[2]);
-
- if (ax >= ay && ax >= az)
- return PLANE_ANYX;
- if (ay >= ax && ay >= az)
- return PLANE_ANYY;
- return PLANE_ANYZ;
- }
- /*
- ================
- PlaneEqual
- ================
- */
- #define NORMAL_EPSILON 0.00001
- #define DIST_EPSILON 0.01
- qboolean PlaneEqual (plane_t *p, vec3_t normal, vec_t dist)
- {
- #if 1
- if (
- fabs(p->normal[0] - normal[0]) < NORMAL_EPSILON
- && fabs(p->normal[1] - normal[1]) < NORMAL_EPSILON
- && fabs(p->normal[2] - normal[2]) < NORMAL_EPSILON
- && fabs(p->dist - dist) < DIST_EPSILON )
- return true;
- #else
- if (p->normal[0] == normal[0]
- && p->normal[1] == normal[1]
- && p->normal[2] == normal[2]
- && p->dist == dist)
- return true;
- #endif
- return false;
- }
- /*
- ================
- AddPlaneToHash
- ================
- */
- void AddPlaneToHash (plane_t *p)
- {
- int hash;
- hash = (int)fabs(p->dist) / 8;
- hash &= (PLANE_HASHES-1);
- p->hash_chain = planehash[hash];
- planehash[hash] = p;
- }
- /*
- ================
- CreateNewFloatPlane
- ================
- */
- int CreateNewFloatPlane (vec3_t normal, vec_t dist)
- {
- plane_t *p, temp;
- if (VectorLength(normal) < 0.5)
- Error ("FloatPlane: bad normal");
- // create a new plane
- if (nummapplanes+2 > MAX_MAP_PLANES)
- Error ("MAX_MAP_PLANES");
- p = &mapplanes[nummapplanes];
- VectorCopy (normal, p->normal);
- p->dist = dist;
- p->type = (p+1)->type = PlaneTypeForNormal (p->normal);
- VectorSubtract (vec3_origin, normal, (p+1)->normal);
- (p+1)->dist = -dist;
- nummapplanes += 2;
- // allways put axial planes facing positive first
- if (p->type < 3)
- {
- if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0)
- {
- // flip order
- temp = *p;
- *p = *(p+1);
- *(p+1) = temp;
- AddPlaneToHash (p);
- AddPlaneToHash (p+1);
- return nummapplanes - 1;
- }
- }
- AddPlaneToHash (p);
- AddPlaneToHash (p+1);
- return nummapplanes - 2;
- }
- /*
- ==============
- SnapVector
- ==============
- */
- void SnapVector (vec3_t normal)
- {
- int i;
- for (i=0 ; i<3 ; i++)
- {
- if ( fabs(normal[i] - 1) < NORMAL_EPSILON )
- {
- VectorClear (normal);
- normal[i] = 1;
- break;
- }
- if ( fabs(normal[i] - -1) < NORMAL_EPSILON )
- {
- VectorClear (normal);
- normal[i] = -1;
- break;
- }
- }
- }
- /*
- ==============
- SnapPlane
- ==============
- */
- void SnapPlane (vec3_t normal, vec_t *dist)
- {
- SnapVector (normal);
- if (fabs(*dist-Q_rint(*dist)) < DIST_EPSILON)
- *dist = Q_rint(*dist);
- }
- /*
- =============
- FindFloatPlane
- =============
- */
- #ifndef USE_HASHING
- int FindFloatPlane (vec3_t normal, vec_t dist)
- {
- int i;
- plane_t *p;
- SnapPlane (normal, &dist);
- for (i=0, p=mapplanes ; i<nummapplanes ; i++, p++)
- {
- if (PlaneEqual (p, normal, dist))
- return i;
- }
- return CreateNewFloatPlane (normal, dist);
- }
- #else
- int FindFloatPlane (vec3_t normal, vec_t dist)
- {
- int i;
- plane_t *p;
- int hash, h;
- SnapPlane (normal, &dist);
- hash = (int)fabs(dist) / 8;
- hash &= (PLANE_HASHES-1);
- // search the border bins as well
- for (i=-1 ; i<=1 ; i++)
- {
- h = (hash+i)&(PLANE_HASHES-1);
- for (p = planehash[h] ; p ; p=p->hash_chain)
- {
- if (PlaneEqual (p, normal, dist))
- return p-mapplanes;
- }
- }
- return CreateNewFloatPlane (normal, dist);
- }
- #endif
- /*
- ================
- PlaneFromPoints
- ================
- */
- int PlaneFromPoints (int *p0, int *p1, int *p2)
- {
- vec3_t t1, t2, normal;
- vec_t dist;
- VectorSubtract (p0, p1, t1);
- VectorSubtract (p2, p1, t2);
- CrossProduct (t1, t2, normal);
- VectorNormalize (normal, normal);
- dist = DotProduct (p0, normal);
- return FindFloatPlane (normal, dist);
- }
- //====================================================================
- /*
- ===========
- BrushContents
- ===========
- */
- int BrushContents (mapbrush_t *b)
- {
- int contents;
- side_t *s;
- int i;
- int trans;
- s = &b->original_sides[0];
- contents = s->contents;
- trans = texinfo[s->texinfo].flags;
- for (i=1 ; i<b->numsides ; i++, s++)
- {
- s = &b->original_sides[i];
- trans |= texinfo[s->texinfo].flags;
- if (s->contents != contents)
- {
- printf ("Entity %i, Brush %i: mixed face contents\n"
- , b->entitynum, b->brushnum);
- break;
- }
- }
- // if any side is translucent, mark the contents
- // and change solid to window
- if ( trans & (SURF_TRANS33|SURF_TRANS66) )
- {
- contents |= CONTENTS_TRANSLUCENT;
- if (contents & CONTENTS_SOLID)
- {
- contents &= ~CONTENTS_SOLID;
- contents |= CONTENTS_WINDOW;
- }
- }
- return contents;
- }
- //============================================================================
- /*
- =================
- AddBrushBevels
- Adds any additional planes necessary to allow the brush to be expanded
- against axial bounding boxes
- =================
- */
- void AddBrushBevels (mapbrush_t *b)
- {
- int axis, dir;
- int i, j, k, l, order;
- side_t sidetemp;
- brush_texture_t tdtemp;
- side_t *s, *s2;
- vec3_t normal;
- float dist;
- winding_t *w, *w2;
- vec3_t vec, vec2;
- float d;
- //
- // add the axial planes
- //
- order = 0;
- for (axis=0 ; axis <3 ; axis++)
- {
- for (dir=-1 ; dir <= 1 ; dir+=2, order++)
- {
- // see if the plane is allready present
- for (i=0, s=b->original_sides ; i<b->numsides ; i++,s++)
- {
- if (mapplanes[s->planenum].normal[axis] == dir)
- break;
- }
- if (i == b->numsides)
- { // add a new side
- if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
- Error ("MAX_MAP_BRUSHSIDES");
- nummapbrushsides++;
- b->numsides++;
- VectorClear (normal);
- normal[axis] = dir;
- if (dir == 1)
- dist = b->maxs[axis];
- else
- dist = -b->mins[axis];
- s->planenum = FindFloatPlane (normal, dist);
- s->texinfo = b->original_sides[0].texinfo;
- s->contents = b->original_sides[0].contents;
- s->bevel = true;
- c_boxbevels++;
- }
- // if the plane is not in it canonical order, swap it
- if (i != order)
- {
- sidetemp = b->original_sides[order];
- b->original_sides[order] = b->original_sides[i];
- b->original_sides[i] = sidetemp;
- j = b->original_sides - brushsides;
- tdtemp = side_brushtextures[j+order];
- side_brushtextures[j+order] = side_brushtextures[j+i];
- side_brushtextures[j+i] = tdtemp;
- }
- }
- }
- //
- // add the edge bevels
- //
- if (b->numsides == 6)
- return; // pure axial
- // test the non-axial plane edges
- for (i=6 ; i<b->numsides ; i++)
- {
- s = b->original_sides + i;
- w = s->winding;
- if (!w)
- continue;
- for (j=0 ; j<w->numpoints ; j++)
- {
- k = (j+1)%w->numpoints;
- VectorSubtract (w->p[j], w->p[k], vec);
- if (VectorNormalize (vec, vec) < 0.5)
- continue;
- SnapVector (vec);
- for (k=0 ; k<3 ; k++)
- if ( vec[k] == -1 || vec[k] == 1)
- break; // axial
- if (k != 3)
- continue; // only test non-axial edges
- // try the six possible slanted axials from this edge
- for (axis=0 ; axis <3 ; axis++)
- {
- for (dir=-1 ; dir <= 1 ; dir+=2)
- {
- // construct a plane
- VectorClear (vec2);
- vec2[axis] = dir;
- CrossProduct (vec, vec2, normal);
- if (VectorNormalize (normal, normal) < 0.5)
- continue;
- dist = DotProduct (w->p[j], normal);
- // if all the points on all the sides are
- // behind this plane, it is a proper edge bevel
- for (k=0 ; k<b->numsides ; k++)
- {
- // if this plane has allready been used, skip it
- if (PlaneEqual (&mapplanes[b->original_sides[k].planenum]
- , normal, dist) )
- break;
- w2 = b->original_sides[k].winding;
- if (!w2)
- continue;
- for (l=0 ; l<w2->numpoints ; l++)
- {
- d = DotProduct (w2->p[l], normal) - dist;
- if (d > 0.1)
- break; // point in front
- }
- if (l != w2->numpoints)
- break;
- }
- if (k != b->numsides)
- continue; // wasn't part of the outer hull
- // add this plane
- if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
- Error ("MAX_MAP_BRUSHSIDES");
- nummapbrushsides++;
- s2 = &b->original_sides[b->numsides];
- s2->planenum = FindFloatPlane (normal, dist);
- s2->texinfo = b->original_sides[0].texinfo;
- s2->contents = b->original_sides[0].contents;
- s2->bevel = true;
- c_edgebevels++;
- b->numsides++;
- }
- }
- }
- }
- }
- /*
- ================
- MakeBrushWindings
- makes basewindigs for sides and mins / maxs for the brush
- ================
- */
- qboolean MakeBrushWindings (mapbrush_t *ob)
- {
- int i, j;
- winding_t *w;
- side_t *side;
- plane_t *plane;
- ClearBounds (ob->mins, ob->maxs);
- for (i=0 ; i<ob->numsides ; i++)
- {
- plane = &mapplanes[ob->original_sides[i].planenum];
- w = BaseWindingForPlane (plane->normal, plane->dist);
- for (j=0 ; j<ob->numsides && w; j++)
- {
- if (i == j)
- continue;
- if (ob->original_sides[j].bevel)
- continue;
- plane = &mapplanes[ob->original_sides[j].planenum^1];
- ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
- }
- side = &ob->original_sides[i];
- side->winding = w;
- if (w)
- {
- side->visible = true;
- for (j=0 ; j<w->numpoints ; j++)
- AddPointToBounds (w->p[j], ob->mins, ob->maxs);
- }
- }
- for (i=0 ; i<3 ; i++)
- {
- if (ob->mins[0] < -4096 || ob->maxs[0] > 4096)
- printf ("entity %i, brush %i: bounds out of range\n", ob->entitynum, ob->brushnum);
- if (ob->mins[0] > 4096 || ob->maxs[0] < -4096)
- printf ("entity %i, brush %i: no visible sides on brush\n", ob->entitynum, ob->brushnum);
- }
- return true;
- }
- /*
- =================
- ParseBrush
- =================
- */
- void ParseBrush (entity_t *mapent)
- {
- mapbrush_t *b;
- int i,j, k;
- int mt;
- side_t *side, *s2;
- int planenum;
- brush_texture_t td;
- int planepts[3][3];
- if (nummapbrushes == MAX_MAP_BRUSHES)
- Error ("nummapbrushes == MAX_MAP_BRUSHES");
- b = &mapbrushes[nummapbrushes];
- b->original_sides = &brushsides[nummapbrushsides];
- b->entitynum = num_entities-1;
- b->brushnum = nummapbrushes - mapent->firstbrush;
- do
- {
- if (!GetToken (true))
- break;
- if (!strcmp (token, "}") )
- break;
- if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
- Error ("MAX_MAP_BRUSHSIDES");
- side = &brushsides[nummapbrushsides];
- // read the three point plane definition
- for (i=0 ; i<3 ; i++)
- {
- if (i != 0)
- GetToken (true);
- if (strcmp (token, "(") )
- Error ("parsing brush");
-
- for (j=0 ; j<3 ; j++)
- {
- GetToken (false);
- planepts[i][j] = atoi(token);
- }
-
- GetToken (false);
- if (strcmp (token, ")") )
- Error ("parsing brush");
-
- }
- //
- // read the texturedef
- //
- GetToken (false);
- strcpy (td.name, token);
- GetToken (false);
- td.shift[0] = atoi(token);
- GetToken (false);
- td.shift[1] = atoi(token);
- GetToken (false);
- td.rotate = atoi(token);
- GetToken (false);
- td.scale[0] = atof(token);
- GetToken (false);
- td.scale[1] = atof(token);
- // find default flags and values
- mt = FindMiptex (td.name);
- td.flags = textureref[mt].flags;
- td.value = textureref[mt].value;
- side->contents = textureref[mt].contents;
- side->surf = td.flags = textureref[mt].flags;
- if (TokenAvailable())
- {
- GetToken (false);
- side->contents = atoi(token);
- GetToken (false);
- side->surf = td.flags = atoi(token);
- GetToken (false);
- td.value = atoi(token);
- }
- // translucent objects are automatically classified as detail
- if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
- side->contents |= CONTENTS_DETAIL;
- if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
- side->contents |= CONTENTS_DETAIL;
- if (fulldetail)
- side->contents &= ~CONTENTS_DETAIL;
- if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1)
- | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST) ) )
- side->contents |= CONTENTS_SOLID;
- // hints and skips are never detail, and have no content
- if (side->surf & (SURF_HINT|SURF_SKIP) )
- {
- side->contents = 0;
- side->surf &= ~CONTENTS_DETAIL;
- }
- //
- // find the plane number
- //
- planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
- if (planenum == -1)
- {
- printf ("Entity %i, Brush %i: plane with no normal\n"
- , b->entitynum, b->brushnum);
- continue;
- }
- //
- // see if the plane has been used already
- //
- for (k=0 ; k<b->numsides ; k++)
- {
- s2 = b->original_sides + k;
- if (s2->planenum == planenum)
- {
- printf ("Entity %i, Brush %i: duplicate plane\n"
- , b->entitynum, b->brushnum);
- break;
- }
- if ( s2->planenum == (planenum^1) )
- {
- printf ("Entity %i, Brush %i: mirrored plane\n"
- , b->entitynum, b->brushnum);
- break;
- }
- }
- if (k != b->numsides)
- continue; // duplicated
- //
- // keep this side
- //
- side = b->original_sides + b->numsides;
- side->planenum = planenum;
- side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
- &td, vec3_origin);
- // save the td off in case there is an origin brush and we
- // have to recalculate the texinfo
- side_brushtextures[nummapbrushsides] = td;
- nummapbrushsides++;
- b->numsides++;
- } while (1);
- // get the content for the entire brush
- b->contents = BrushContents (b);
- // allow detail brushes to be removed
- if (nodetail && (b->contents & CONTENTS_DETAIL) )
- {
- b->numsides = 0;
- return;
- }
- // allow water brushes to be removed
- if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
- {
- b->numsides = 0;
- return;
- }
- // create windings for sides and bounds for brush
- MakeBrushWindings (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;
- }
- //
- // 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
- //
- 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;
- }
- AddBrushBevels (b);
- nummapbrushes++;
- mapent->numbrushes++;
- }
- /*
- ================
- MoveBrushesToWorld
- Takes all of the brushes from the current entity and
- adds them to the world's brush list.
- Used by func_group and func_areaportal
- ================
- */
- void MoveBrushesToWorld (entity_t *mapent)
- {
- int newbrushes;
- int worldbrushes;
- mapbrush_t *temp;
- int i;
- // this is pretty gross, because the brushes are expected to be
- // in linear order for each entity
- newbrushes = mapent->numbrushes;
- worldbrushes = entities[0].numbrushes;
- temp = malloc(newbrushes*sizeof(mapbrush_t));
- memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t));
- #if 0 // let them keep their original brush numbers
- for (i=0 ; i<newbrushes ; i++)
- temp[i].entitynum = 0;
- #endif
- // make space to move the brushes (overlapped copy)
- memmove (mapbrushes + worldbrushes + newbrushes,
- mapbrushes + worldbrushes,
- sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes) );
- // copy the new brushes down
- memcpy (mapbrushes + worldbrushes, temp, sizeof(mapbrush_t) * newbrushes);
- // fix up indexes
- entities[0].numbrushes += newbrushes;
- for (i=1 ; i<num_entities ; i++)
- entities[i].firstbrush += newbrushes;
- free (temp);
- mapent->numbrushes = 0;
- }
- /*
- ================
- ParseMapEntity
- ================
- */
- qboolean ParseMapEntity (void)
- {
- entity_t *mapent;
- epair_t *e;
- side_t *s;
- int i, j;
- int startbrush, startsides;
- vec_t newdist;
- mapbrush_t *b;
- if (!GetToken (true))
- return false;
- if (strcmp (token, "{") )
- Error ("ParseEntity: { not found");
-
- if (num_entities == MAX_MAP_ENTITIES)
- Error ("num_entities == MAX_MAP_ENTITIES");
- startbrush = nummapbrushes;
- startsides = nummapbrushsides;
- mapent = &entities[num_entities];
- num_entities++;
- memset (mapent, 0, sizeof(*mapent));
- mapent->firstbrush = nummapbrushes;
- mapent->numbrushes = 0;
- // mapent->portalareas[0] = -1;
- // mapent->portalareas[1] = -1;
- do
- {
- if (!GetToken (true))
- Error ("ParseEntity: EOF without closing brace");
- if (!strcmp (token, "}") )
- break;
- if (!strcmp (token, "{") )
- ParseBrush (mapent);
- else
- {
- e = ParseEpair ();
- e->next = mapent->epairs;
- mapent->epairs = e;
- }
- } while (1);
- GetVectorForKey (mapent, "origin", mapent->origin);
- //
- // if there was an origin brush, offset all of the planes and texinfo
- //
- if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
- {
- for (i=0 ; i<mapent->numbrushes ; i++)
- {
- b = &mapbrushes[mapent->firstbrush + i];
- for (j=0 ; j<b->numsides ; j++)
- {
- s = &b->original_sides[j];
- newdist = mapplanes[s->planenum].dist -
- DotProduct (mapplanes[s->planenum].normal, mapent->origin);
- s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
- s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
- &side_brushtextures[s-brushsides], mapent->origin);
- }
- MakeBrushWindings (b);
- }
- }
- // group entities are just for editor convenience
- // toss all brushes into the world entity
- if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
- {
- MoveBrushesToWorld (mapent);
- mapent->numbrushes = 0;
- return true;
- }
- // areaportal entities move their brushes, but don't eliminate
- // the entity
- if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
- {
- char str[128];
- if (mapent->numbrushes != 1)
- Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1);
- b = &mapbrushes[nummapbrushes-1];
- b->contents = CONTENTS_AREAPORTAL;
- c_areaportals++;
- mapent->areaportalnum = c_areaportals;
- // set the portal number as "style"
- sprintf (str, "%i", c_areaportals);
- SetKeyValue (mapent, "style", str);
- MoveBrushesToWorld (mapent);
- return true;
- }
- return true;
- }
- //===================================================================
- /*
- ================
- LoadMapFile
- ================
- */
- void LoadMapFile (char *filename)
- {
- int i;
- qprintf ("--- LoadMapFile ---\n");
- LoadScriptFile (filename);
- nummapbrushsides = 0;
- num_entities = 0;
-
- while (ParseMapEntity ())
- {
- }
- ClearBounds (map_mins, map_maxs);
- for (i=0 ; i<entities[0].numbrushes ; i++)
- {
- if (mapbrushes[i].mins[0] > 4096)
- continue; // no valid points
- AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
- AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
- }
- qprintf ("%5i brushes\n", nummapbrushes);
- qprintf ("%5i clipbrushes\n", c_clipbrushes);
- qprintf ("%5i total sides\n", nummapbrushsides);
- qprintf ("%5i boxbevels\n", c_boxbevels);
- qprintf ("%5i edgebevels\n", c_edgebevels);
- qprintf ("%5i entities\n", num_entities);
- qprintf ("%5i planes\n", nummapplanes);
- qprintf ("%5i areaportals\n", c_areaportals);
- qprintf ("size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", map_mins[0],map_mins[1],map_mins[2],
- map_maxs[0],map_maxs[1],map_maxs[2]);
- // TestExpandBrushes ();
- }
- //====================================================================
- /*
- ================
- TestExpandBrushes
- Expands all the brush planes and saves a new map out
- ================
- */
- void TestExpandBrushes (void)
- {
- FILE *f;
- side_t *s;
- int i, j, bn;
- winding_t *w;
- char *name = "expanded.map";
- mapbrush_t *brush;
- vec_t dist;
- printf ("writing %s\n", name);
- f = fopen (name, "wb");
- if (!f)
- Error ("Can't write %s\b", name);
- fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
- for (bn=0 ; bn<nummapbrushes ; bn++)
- {
- brush = &mapbrushes[bn];
- fprintf (f, "{\n");
- for (i=0 ; i<brush->numsides ; i++)
- {
- s = brush->original_sides + i;
- dist = mapplanes[s->planenum].dist;
- for (j=0 ; j<3 ; j++)
- dist += fabs( 16 * mapplanes[s->planenum].normal[j] );
- w = BaseWindingForPlane (mapplanes[s->planenum].normal, dist);
- fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
- fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
- fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
- fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture);
- FreeWinding (w);
- }
- fprintf (f, "}\n");
- }
- fprintf (f, "}\n");
- fclose (f);
- Error ("can't proceed after expanding brushes");
- }
|