📄 map_hl.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_bsp_hl.h"
#include "aas_map.h" //AAS_CreateMapBrushes
int hl_numbrushes;
int hl_numclipbrushes;
//#define HL_PRINT
#define HLCONTENTS
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int HL_TextureContents(char *name)
{
if (!Q_strncasecmp (name, "sky",3))
return CONTENTS_SOLID;
if (!Q_strncasecmp(name+1,"!lava",5))
return CONTENTS_LAVA;
if (!Q_strncasecmp(name+1,"!slime",6))
return CONTENTS_SLIME;
/*
if (!Q_strncasecmp (name, "!cur_90",7))
return CONTENTS_CURRENT_90;
if (!Q_strncasecmp (name, "!cur_0",6))
return CONTENTS_CURRENT_0;
if (!Q_strncasecmp (name, "!cur_270",8))
return CONTENTS_CURRENT_270;
if (!Q_strncasecmp (name, "!cur_180",8))
return CONTENTS_CURRENT_180;
if (!Q_strncasecmp (name, "!cur_up",7))
return CONTENTS_CURRENT_UP;
if (!Q_strncasecmp (name, "!cur_dwn",8))
return CONTENTS_CURRENT_DOWN;
//*/
if (name[0] == '!')
return CONTENTS_WATER;
/*
if (!Q_strncasecmp (name, "origin",6))
return CONTENTS_ORIGIN;
if (!Q_strncasecmp (name, "clip",4))
return CONTENTS_CLIP;
if( !Q_strncasecmp( name, "translucent", 11 ) )
return CONTENTS_TRANSLUCENT;
if( name[0] == '@' )
return CONTENTS_TRANSLUCENT;
//*/
return CONTENTS_SOLID;
} //end of the function HL_TextureContents
//===========================================================================
// Generates two new brushes, leaving the original
// unchanged
//
// modified for Half-Life because there are quite a lot of tiny node leaves
// in the Half-Life bsps
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
void HL_SplitBrush(bspbrush_t *brush, int planenum, int nodenum,
bspbrush_t **front, bspbrush_t **back)
{
bspbrush_t *b[2];
int i, j;
winding_t *w, *cw[2], *midwinding;
plane_t *plane, *plane2;
side_t *s, *cs;
float d, d_front, d_back;
*front = *back = NULL;
plane = &mapplanes[planenum];
// check all points
d_front = d_back = 0;
for (i=0 ; i<brush->numsides ; i++)
{
w = brush->sides[i].winding;
if (!w)
continue;
for (j=0 ; j<w->numpoints ; j++)
{
d = DotProduct (w->p[j], plane->normal) - plane->dist;
if (d > 0 && d > d_front)
d_front = d;
if (d < 0 && d < d_back)
d_back = d;
} //end for
} //end for
if (d_front < 0.1) // PLANESIDE_EPSILON)
{ // only on back
*back = CopyBrush (brush);
Log_Print("HL_SplitBrush: only on back\n");
return;
} //end if
if (d_back > -0.1) // PLANESIDE_EPSILON)
{ // only on front
*front = CopyBrush (brush);
Log_Print("HL_SplitBrush: only on front\n");
return;
} //end if
// create a new winding from the split plane
w = BaseWindingForPlane (plane->normal, plane->dist);
for (i = 0; i < brush->numsides && w; i++)
{
plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
ChopWindingInPlace(&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON);
} //end for
if (!w || WindingIsTiny(w))
{ // the brush isn't really split
int side;
Log_Print("HL_SplitBrush: no split winding\n");
side = BrushMostlyOnSide (brush, plane);
if (side == PSIDE_FRONT)
*front = CopyBrush (brush);
if (side == PSIDE_BACK)
*back = CopyBrush (brush);
return;
}
if (WindingIsHuge(w))
{
Log_Print("HL_SplitBrush: WARNING huge split winding\n");
} //end of
midwinding = w;
// split it for real
for (i = 0; i < 2; i++)
{
b[i] = AllocBrush (brush->numsides+1);
b[i]->original = brush->original;
} //end for
// split all the current windings
for (i=0 ; i<brush->numsides ; i++)
{
s = &brush->sides[i];
w = s->winding;
if (!w)
continue;
ClipWindingEpsilon (w, plane->normal, plane->dist,
0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]);
for (j=0 ; j<2 ; j++)
{
if (!cw[j])
continue;
#if 0
if (WindingIsTiny (cw[j]))
{
FreeWinding (cw[j]);
continue;
}
#endif
cs = &b[j]->sides[b[j]->numsides];
b[j]->numsides++;
*cs = *s;
// cs->planenum = s->planenum;
// cs->texinfo = s->texinfo;
// cs->visible = s->visible;
// cs->original = s->original;
cs->winding = cw[j];
cs->flags &= ~SFL_TESTED;
} //end for
} //end for
// see if we have valid polygons on both sides
for (i=0 ; i<2 ; i++)
{
BoundBrush (b[i]);
for (j=0 ; j<3 ; j++)
{
if (b[i]->mins[j] < -4096 || b[i]->maxs[j] > 4096)
{
Log_Print("HL_SplitBrush: bogus brush after clip\n");
break;
} //end if
} //end for
if (b[i]->numsides < 3 || j < 3)
{
FreeBrush (b[i]);
b[i] = NULL;
Log_Print("HL_SplitBrush: numsides < 3\n");
} //end if
} //end for
if ( !(b[0] && b[1]) )
{
if (!b[0] && !b[1])
Log_Print("HL_SplitBrush: split removed brush\n");
else
Log_Print("HL_SplitBrush: split not on both sides\n");
if (b[0])
{
FreeBrush (b[0]);
*front = CopyBrush (brush);
} //end if
if (b[1])
{
FreeBrush (b[1]);
*back = CopyBrush (brush);
} //end if
return;
} //end if
// add the midwinding to both sides
for (i = 0; i < 2; i++)
{
cs = &b[i]->sides[b[i]->numsides];
b[i]->numsides++;
cs->planenum = planenum^i^1;
cs->texinfo = 0;
//store the node number in the surf to find the texinfo later on
cs->surf = nodenum;
//
cs->flags &= ~SFL_VISIBLE;
cs->flags &= ~SFL_TESTED;
if (i==0)
cs->winding = CopyWinding (midwinding);
else
cs->winding = midwinding;
} //end for
{
vec_t v1;
int i;
for (i=0 ; i<2 ; i++)
{
v1 = BrushVolume (b[i]);
if (v1 < 1)
{
FreeBrush (b[i]);
b[i] = NULL;
Log_Print("HL_SplitBrush: tiny volume after clip\n");
} //end if
} //end for
} //*/
*front = b[0];
*back = b[1];
} //end of the function HL_SplitBrush
//===========================================================================
// returns true if the tree starting at nodenum has only solid leaves
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
int HL_SolidTree_r(int nodenum)
{
if (nodenum < 0)
{
switch(hl_dleafs[(-nodenum) - 1].contents)
{
case HL_CONTENTS_EMPTY:
{
return false;
} //end case
case HL_CONTENTS_SOLID:
#ifdef HLCONTENTS
case HL_CONTENTS_CLIP:
#endif //HLCONTENTS
case HL_CONTENTS_SKY:
#ifdef HLCONTENTS
case HL_CONTENTS_TRANSLUCENT:
#endif //HLCONTENTS
{
return true;
} //end case
case HL_CONTENTS_WATER:
case HL_CONTENTS_SLIME:
case HL_CONTENTS_LAVA:
#ifdef HLCONTENTS
//these contents should not be found in the BSP
case HL_CONTENTS_ORIGIN:
case HL_CONTENTS_CURRENT_0:
case HL_CONTENTS_CURRENT_90:
case HL_CONTENTS_CURRENT_180:
case HL_CONTENTS_CURRENT_270:
case HL_CONTENTS_CURRENT_UP:
case HL_CONTENTS_CURRENT_DOWN:
#endif //HLCONTENTS
default:
{
return false;
} //end default
} //end switch
return false;
} //end if
if (!HL_SolidTree_r(hl_dnodes[nodenum].children[0])) return false;
if (!HL_SolidTree_r(hl_dnodes[nodenum].children[1])) return false;
return true;
} //end of the function HL_SolidTree_r
//===========================================================================
//
// Parameter: -
// Returns: -
// Changes Globals: -
//===========================================================================
bspbrush_t *HL_CreateBrushes_r(bspbrush_t *brush, int nodenum)
{
int planenum;
bspbrush_t *front, *back;
hl_dleaf_t *leaf;
//if it is a leaf
if (nodenum < 0)
{
leaf = &hl_dleafs[(-nodenum) - 1];
if (leaf->contents != HL_CONTENTS_EMPTY)
{
#ifdef HL_PRINT
qprintf("\r%5i", ++hl_numbrushes);
#endif //HL_PRINT
} //end if
switch(leaf->contents)
{
case HL_CONTENTS_EMPTY:
{
FreeBrush(brush);
return NULL;
} //end case
case HL_CONTENTS_SOLID:
#ifdef HLCONTENTS
case HL_CONTENTS_CLIP:
#endif //HLCONTENTS
case HL_CONTENTS_SKY:
#ifdef HLCONTENTS
case HL_CONTENTS_TRANSLUCENT:
#endif //HLCONTENTS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -