📄 map_q3.c
字号:
/*
===========================================================================
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"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -