예제 #1
0
/*
====================
CheckWindingInAreas_r

Returns the area number that the winding is in, or
-2 if it crosses multiple areas.

====================
*/
static int CheckWindingInAreas_r( const idWinding* w, node_t* node )
{
	idWinding*		front, *back;
	
	if( !w )
	{
		return -1;
	}
	
	if( node->planenum != PLANENUM_LEAF )
	{
		int		a1, a2;
#if 0
		if( side->planenum == node->planenum )
		{
			return CheckWindingInAreas_r( w, node->children[0] );
		}
		if( side->planenum == ( node->planenum ^ 1 ) )
		{
			return CheckWindingInAreas_r( w, node->children[1] );
		}
#endif
		w->Split( dmapGlobals.mapPlanes[ node->planenum ], ON_EPSILON, &front, &back );
		
		a1 = CheckWindingInAreas_r( front, node->children[0] );
		delete front;
		a2 = CheckWindingInAreas_r( back, node->children[1] );
		delete back;
		
		if( a1 == -2 || a2 == -2 )
		{
			return -2;	// different
		}
		if( a1 == -1 )
		{
			return a2;	// one solid
		}
		if( a2 == -1 )
		{
			return a1;	// one solid
		}
		
		if( a1 != a2 )
		{
			return -2;	// cross areas
		}
		return a1;
	}
	
	return node->area;
}
/*
====================
PutWindingIntoAreas_r

Clips a winding down into the bsp tree, then converts
the fragments to triangles and adds them to the area lists
====================
*/
static void PutWindingIntoAreas_r( uEntity_t *e, const idWinding *w, side_t *side, node_t *node ) {
	idWinding		*front, *back;
	int				area;

	if ( !w ) {
		return;
	}

	if ( node->planenum != PLANENUM_LEAF ) {
		if ( side->planenum == node->planenum ) {
			PutWindingIntoAreas_r( e, w, side, node->children[0] );
			return;
		}
		if ( side->planenum == ( node->planenum ^ 1) ) {
			PutWindingIntoAreas_r( e, w, side, node->children[1] );
			return;
		}

		// see if we need to split it
		// adding the "noFragment" flag to big surfaces like sky boxes
		// will avoid potentially dicing them up into tons of triangles
		// that take forever to optimize back together
		if ( !dmapGlobals.fullCarve || side->material->NoFragment() ) {
			area = CheckWindingInAreas_r( w, node );
			if ( area >= 0 ) {
				mapTri_t	*tri;

				// put in single area
				tri = TriListForSide( side, w );
				AddTriListToArea( e, tri, side->planenum, area, &side->texVec );
				return;
			}
		}

		w->Split( dmapGlobals.mapPlanes[ node->planenum ], ON_EPSILON, &front, &back );

		PutWindingIntoAreas_r( e, front, side, node->children[0] );
		if ( front ) {
			delete front;
		}

		PutWindingIntoAreas_r( e, back, side, node->children[1] );
		if ( back ) {
			delete back;
		}

		return;
	}

	// if opaque leaf, don't add
	if ( node->area >= 0 && !node->opaque ) {
		mapTri_t	*tri;

		tri = TriListForSide( side, w );
		AddTriListToArea( e, tri, side->planenum, node->area, &side->texVec );
	}
}
예제 #3
0
/*
==================
AddMapTriToAreas

Used for curves and inlined models
==================
*/
void AddMapTriToAreas( mapTri_t* tri, uEntity_t* e )
{
	int				area;
	idWinding*		w;
	
	// skip degenerate triangles from pinched curves
	if( MapTriArea( tri ) <= 0 )
	{
		return;
	}
	
	if( dmapGlobals.fullCarve )
	{
		// always fragment into areas
		w = WindingForTri( tri );
		ClipTriIntoTree_r( w, tri, e, e->tree->headnode );
		return;
	}
	
	w = WindingForTri( tri );
	area = CheckWindingInAreas_r( w, e->tree->headnode );
	delete w;
	if( area == -1 )
	{
		return;
	}
	if( area >= 0 )
	{
		mapTri_t*	newTri;
		idPlane		plane;
		int			planeNum;
		textureVectors_t	texVec;
		
		// put in single area
		newTri = CopyMapTri( tri );
		newTri->next = NULL;
		
		PlaneForTri( tri, plane );
		planeNum = FindFloatPlane( plane );
		
		TexVecForTri( &texVec, newTri );
		
		AddTriListToArea( e, newTri, planeNum, area, &texVec );
	}
	else
	{
		// fragment into areas
		w = WindingForTri( tri );
		ClipTriIntoTree_r( w, tri, e, e->tree->headnode );
	}
}