/*
============
QuickTestBrushToPlanenum

============
*/
int	QuickTestBrushToPlanenum (bspbrush_t *brush, int planenum, int *numsplits)
{
	int			i, num;
	plane_t		*plane;
	int			s;

	*numsplits = 0;

	// if the brush actually uses the planenum,
	// we can tell the side for sure
	for (i=0 ; i<brush->numsides ; i++)
	{
		num = brush->sides[i].planenum;
		if (num >= MAX_MAP_PLANES)
			Error ("bad planenum");
		if (num == planenum)
			return PSIDE_BACK|PSIDE_FACING;
		if (num == (planenum ^ 1) )
			return PSIDE_FRONT|PSIDE_FACING;
	}

	// box on plane side
	plane = &g_MainMap->mapplanes[planenum];
	s = BrushBspBoxOnPlaneSide (brush->mins, brush->maxs, plane);

	// if both sides, count the visible faces split
	if (s == PSIDE_BOTH)
	{
		*numsplits += 3;
	}

	return s;
}
Esempio n. 2
0
//-----------------------------------------------------------------------------
// Check to see if a displacement lives in any leaves that are not
// in the 3d skybox
//-----------------------------------------------------------------------------
bool IsBoxInsideWorld( int node, CUtlVector<int> &skipAreas, const Vector &vecMins, const Vector &vecMaxs )
{
    while( 1 )
    {
        // leaf
        if (node < 0)
        {
            // get the leaf
            int leaf = - 1 - node;

            // Don't bother with solid leaves
            if (dleafs[leaf].contents & CONTENTS_SOLID)
                return false;

            // Skip 3D skybox
            int i;
            for ( i = skipAreas.Count(); --i >= 0; )
            {
                if ( dleafs[leaf].area == skipAreas[i] )
                    return false;
            }

            return true;
        }

        //
        // get displacement bounding box position relative to the node plane
        //
        dnode_t *pNode = &dnodes[ node ];
        dplane_t *pPlane = &dplanes[ pNode->planenum ];

        int sideResult = BrushBspBoxOnPlaneSide( vecMins, vecMaxs, pPlane );

        // front side
        if( sideResult == 1 )
        {
            node = pNode->children[0];
        }
        // back side
        else if( sideResult == 2 )
        {
            node = pNode->children[1];
        }
        //split
        else
        {
            if ( IsBoxInsideWorld( pNode->children[0], skipAreas, vecMins, vecMaxs ) )
                return true;

            node = pNode->children[1];
        }
    }
}
/*
============
TestBrushToPlanenum

============
*/
int	TestBrushToPlanenum (bspbrush_t *brush, int planenum,
						 int *numsplits, qboolean *hintsplit, int *epsilonbrush)
{
	int			i, j, num;
	plane_t		*plane;
	int			s;
	winding_t	*w;
	vec_t		d, d_front, d_back;
	int			front, back;

	*numsplits = 0;
	*hintsplit = false;

	// if the brush actually uses the planenum,
	// we can tell the side for sure
	for (i=0 ; i<brush->numsides ; i++)
	{
		num = brush->sides[i].planenum;
		if (num >= MAX_MAP_PLANES)
			Error ("bad planenum");
		if (num == planenum)
			return PSIDE_BACK|PSIDE_FACING;
		if (num == (planenum ^ 1) )
			return PSIDE_FRONT|PSIDE_FACING;
	}

	// box on plane side
	plane = &g_MainMap->mapplanes[planenum];
	s = BrushBspBoxOnPlaneSide (brush->mins, brush->maxs, plane);

	if (s != PSIDE_BOTH)
		return s;

// if both sides, count the visible faces split
	d_front = d_back = 0;

	for (i=0 ; i<brush->numsides ; i++)
	{
		if (brush->sides[i].texinfo == TEXINFO_NODE)
			continue;		// on node, don't worry about splits
		if (!brush->sides[i].visible)
			continue;		// we don't care about non-visible
		w = brush->sides[i].winding;
		if (!w)
			continue;

		front = back = 0;
		for (j=0 ; j<w->numpoints; j++)
		{
			d = DotProduct (w->p[j], plane->normal) - plane->dist;

			if (d > d_front)
				d_front = d;
			if (d < d_back)
				d_back = d;

			if (d > 0.1) // PLANESIDE_EPSILON)
				front = 1;
			if (d < -0.1) // PLANESIDE_EPSILON)
				back = 1;
		}

		if (front && back)
		{
			if ( !(brush->sides[i].surf & SURF_SKIP) )
			{
				(*numsplits)++;
				if (brush->sides[i].surf & SURF_HINT)
					*hintsplit = true;
			}
		}
	}

	if ( (d_front > 0.0 && d_front < 1.0)
		|| (d_back < 0.0 && d_back > -1.0) )
		(*epsilonbrush)++;

#if 0
	if (*numsplits == 0)
	{	//	didn't really need to be split
		if (front)
			s = PSIDE_FRONT;
		else if (back)
			s = PSIDE_BACK;
		else
			s = 0;
	}
#endif

	return s;
}