/*
================
SplitBrushList
================
*/
void SplitBrushList (bspbrush_t *brushes, 
	node_t *node, bspbrush_t **front, bspbrush_t **back)
{
	bspbrush_t	*brush, *newbrush, *newbrush2;
	side_t		*side;
	int			sides;
	int			i;

	*front = *back = NULL;

	for (brush = brushes ; brush ; brush=brush->next)
	{
		sides = brush->side;

		if (sides == PSIDE_BOTH)
		{	// split into two brushes
			SplitBrush (brush, node->planenum, &newbrush, &newbrush2);
			if (newbrush)
			{
				newbrush->next = *front;
				*front = newbrush;
			}
			if (newbrush2)
			{
				newbrush2->next = *back;
				*back = newbrush2;
			}
			continue;
		}

		newbrush = CopyBrush (brush);

		// if the planenum is actualy a part of the brush
		// find the plane and flag it as used so it won't be tried
		// as a splitter again
		if (sides & PSIDE_FACING)
		{
			for (i=0 ; i<newbrush->numsides ; i++)
			{
				side = newbrush->sides + i;
				if ( (side->planenum& ~1) == node->planenum)
					side->texinfo = TEXINFO_NODE;
			}
		}


		if (sides & PSIDE_FRONT)
		{
			newbrush->next = *front;
			*front = newbrush;
			continue;
		}
		if (sides & PSIDE_BACK)
		{
			newbrush->next = *back;
			*back = newbrush;
			continue;
		}
	}
}
Exemple #2
0
//-----------------------------------------------------------------------------
// Purpose: Recursively filter a brush through the tree
// Input  : *node - 
//			*brush - 
//-----------------------------------------------------------------------------
void MergeBrush_r( node_t *node, bspbrush_t *brush )
{
	if ( node->planenum == PLANENUM_LEAF )
	{
		if ( node->contents & CONTENTS_SOLID )
		{
			FreeBrush( brush );
		}
		else
		{
			AddBrushToLeaf( node, brush );
		}
		return;
	}

	bspbrush_t *front, *back;
	SplitBrush( brush, node->planenum, &front, &back );
	FreeBrush( brush );

	if ( front )
	{
		MergeBrush_r( node->children[0], front );
	}
	if ( back )
	{
		MergeBrush_r( node->children[1], back );
	}
}
Exemple #3
0
//===========================================================================
// Returns a single brush made up by the intersection of the
// two provided brushes, or NULL if they are disjoint.
//
// The originals are undisturbed.
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *IntersectBrush( bspbrush_t *a, bspbrush_t *b ) {
	int i;
	bspbrush_t  *front, *back;
	bspbrush_t  *in;

	in = a;
	for ( i = 0 ; i < b->numsides && in ; i++ )
	{
		SplitBrush( in, b->sides[i].planenum, &front, &back );
//		SplitBrush2(in, b->sides[i].planenum, &front, &back);
		if ( in != a ) {
			FreeBrush( in );
		}
		if ( front ) {
			FreeBrush( front );
		}
		in = back;
	} //end for

	if ( in == a ) {
		return NULL;
	}

	in->next = NULL;
	return in;
} //end of the function IntersectBrush
Exemple #4
0
//===========================================================================
// Returns a list of brushes that remain after B is subtracted from A.
// May by empty if A is contained inside B.
// The originals are undisturbed.
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *SubtractBrush( bspbrush_t *a, bspbrush_t *b ) { // a - b = out (list)
	int i;
	bspbrush_t  *front, *back;
	bspbrush_t  *out, *in;

	in = a;
	out = NULL;
	for ( i = 0; i < b->numsides && in; i++ )
	{
		SplitBrush( in, b->sides[i].planenum, &front, &back );
//		SplitBrush2(in, b->sides[i].planenum, &front, &back);
		if ( in != a ) {
			FreeBrush( in );
		}
		if ( front ) { // add to list
			front->next = out;
			out = front;
		} //end if
		in = back;
	} //end for
	if ( in ) {
		FreeBrush( in );
	} //end if
	else
	{   // didn't really intersect
		FreeBrushList( out );
		return a;
	} //end else
	return out;
} //end of the function SubtractBrush
Exemple #5
0
/*
====================
FilterBrushIntoTree_r

====================
*/
int FilterBrushIntoTree_r( uBrush_t *b, node_t *node )
{
	uBrush_t		*front, *back;
	int				c;
	
	if( !b )
	{
		return 0;
	}
	
	// add it to the leaf list
	if( node->planenum == PLANENUM_LEAF )
	{
		b->next = node->brushlist;
		node->brushlist = b;
		
		// classify the leaf by the structural brush
		if( b->opaque )
		{
			node->opaque = true;
		}
		return 1;
	}
	
	// split it by the node plane
	SplitBrush( b, node->planenum, &front, &back );
	FreeBrush( b );
	
	c = 0;
	c += FilterBrushIntoTree_r( front, node->children[0] );
	c += FilterBrushIntoTree_r( back, node->children[1] );
	
	return c;
}
Exemple #6
0
void SplitBrushList (bspbrush_t* brushes, uint16_t planenum, bspbrush_t** front, bspbrush_t** back)
{
	bspbrush_t* brush;

	*front = *back = nullptr;

	for (brush = brushes; brush; brush = brush->next) {
		const int sides = brush->side;
		bspbrush_t* newbrush;

		if (sides == PSIDE_BOTH) {	/* split into two brushes */
			bspbrush_t* newbrush2;
			SplitBrush(brush, planenum, &newbrush, &newbrush2);
			if (newbrush) {
				newbrush->next = *front;
				Verb_Printf(VERB_DUMP, "SplitBrushList: Adding brush %i to front list.\n", newbrush->original->brushnum);
				*front = newbrush;
			}
			if (newbrush2) {
				newbrush2->next = *back;
				Verb_Printf(VERB_DUMP, "SplitBrushList: Adding brush %i to back list.\n", newbrush2->original->brushnum);
				*back = newbrush2;
			}
			continue;
		}

		newbrush = CopyBrush(brush);

		/* if the planenum is actually a part of the brush
		 * find the plane and flag it as used so it won't be tried
		 * as a splitter again */
		if (sides & PSIDE_FACING) {
			int i;
			for (i = 0; i < newbrush->numsides; i++) {
				side_t* side = newbrush->sides + i;
				if ((side->planenum & ~1) == planenum)
					side->texinfo = TEXINFO_NODE;
			}
		}

		if (sides & PSIDE_FRONT) {
			newbrush->next = *front;
			*front = newbrush;
			Verb_Printf(VERB_DUMP, "SplitBrushList: Adding brush %i to front list.\n", newbrush->original->brushnum);
			continue;
		}
		if (sides & PSIDE_BACK) {
			newbrush->next = *back;
			Verb_Printf(VERB_DUMP, "SplitBrushList: Adding brush %i to back list.\n", newbrush->original->brushnum);
			*back = newbrush;
			continue;
		}
		Verb_Printf(VERB_DUMP, "SplitBrushList: Brush %i fell off the map.\n", newbrush->original->brushnum);
	}
}
Exemple #7
0
//===========================================================================
// Any planes shared with the box edge will be set to no texinfo
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *ClipBrushToBox(bspbrush_t *brush, vec3_t clipmins, vec3_t clipmaxs)
{
	int		i, j;
	bspbrush_t	*front,	*back;
	int		p;

	for (j=0 ; j<2 ; j++)
	{
		if (brush->maxs[j] > clipmaxs[j])
		{
			SplitBrush (brush, maxplanenums[j], &front, &back);
			if (front)
				FreeBrush (front);
			brush = back;
			if (!brush)
				return NULL;
		}
		if (brush->mins[j] < clipmins[j])
		{
			SplitBrush (brush, minplanenums[j], &front, &back);
			if (back)
				FreeBrush (back);
			brush = front;
			if (!brush)
				return NULL;
		}
	}

	// remove any colinear faces

	for (i=0 ; i<brush->numsides ; i++)
	{
		p = brush->sides[i].planenum & ~1;
		if (p == maxplanenums[0] || p == maxplanenums[1] 
			|| p == minplanenums[0] || p == minplanenums[1])
		{
			brush->sides[i].texinfo = TEXINFO_NODE;
			brush->sides[i].flags &= ~SFL_VISIBLE;
		}
	}
	return brush;
} //end of the function ClipBrushToBox
Exemple #8
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void SplitBrush2 (bspbrush_t *brush, int planenum,
	bspbrush_t **front, bspbrush_t **back)
{
	SplitBrush (brush, planenum, front, back);
#if 0
	if (*front && (*front)->sides[(*front)->numsides-1].texinfo == -1)
		(*front)->sides[(*front)->numsides-1].texinfo = (*front)->sides[0].texinfo;	// not -1
	if (*back && (*back)->sides[(*back)->numsides-1].texinfo == -1)
		(*back)->sides[(*back)->numsides-1].texinfo = (*back)->sides[0].texinfo;	// not -1
#endif
} //end of the function SplitBrush2
Exemple #9
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
qboolean CheckPlaneAgainstVolume (int pnum, node_t *node)
{
	bspbrush_t	*front, *back;
	qboolean	good;

	SplitBrush (node->volume, pnum, &front, &back);

	good = (front && back);

	if (front) FreeBrush (front);
	if (back) FreeBrush (back);

	return good;
} //end of the function CheckPlaneAgaintsVolume
Exemple #10
0
/*
================
BuildTree_r
================
*/
node_t *BuildTree_r (node_t *node, bspbrush_t *brushes)
{
	node_t		*newnode;
	side_t		*bestside;
	int			i;
	bspbrush_t	*children[2];

	if (numthreads == 1)
		c_nodes++;

	if (drawflag)
		DrawBrushList (brushes, node);

	// find the best plane to use as a splitter
	bestside = SelectSplitSide (brushes, node);
	if (!bestside)
	{
		// leaf node
		node->side = NULL;
		node->planenum = -1;
		LeafNode (node, brushes);
		return node;
	}

	// this is a splitplane node
	node->side = bestside;
	node->planenum = bestside->planenum & ~1;	// always use front facing

	SplitBrushList (brushes, node, &children[0], &children[1]);
	FreeBrushList (brushes);

	// allocate children before recursing
	for (i=0 ; i<2 ; i++)
	{
		newnode = AllocNode ();
		newnode->parent = node;
		node->children[i] = newnode;
	}

	SplitBrush (node->volume, node->planenum, &node->children[0]->volume,
		&node->children[1]->volume);

	// recursively process children
	for (i=0 ; i<2 ; i++)
	{
		node->children[i] = BuildTree_r (node->children[i], children[i]);
	}

	return node;
}
Exemple #11
0
static bool CheckPlaneAgainstVolume (uint16_t pnum, const bspbrush_t* volume)
{
		bspbrush_t* front, *back;
		bool good;

		SplitBrush(volume, pnum, &front, &back);

		good = (front && back);

		if (front)
				FreeBrush(front);
		if (back)
				FreeBrush(back);

		return good;
}
Exemple #12
0
static node_t *BuildTree_r (node_t *node, bspbrush_t *brushes)
{
	node_t *newnode;
	side_t *bestside;
	int i;
	bspbrush_t *children[2];

	if (threadstate.numthreads == 1)
		c_nodes++;

	/* find the best plane to use as a splitter */
	bestside = SelectSplitSide(brushes, node->volume);
	if (!bestside) {
		/* leaf node */
		LeafNode(node, brushes);
		Verb_Printf(VERB_DUMP, "BuildTree_r: Created a leaf node.\n");
		return node;
	}
	/* make sure the selected plane hasn't been used before. */
	CheckPlaneAgainstParents(bestside->planenum, node);

	Verb_Printf(VERB_DUMP, "BuildTree_r: splitting along plane %i\n", (int)bestside->planenum);

	/* this is a splitplane node */
	node->side = bestside;
	node->planenum = bestside->planenum & ~1;	/* always use front facing */

	SplitBrushList(brushes, node->planenum, &children[0], &children[1]);
	FreeBrushList(brushes);

	/* allocate children before recursing */
	for (i = 0; i < 2; i++) {
		newnode = AllocNode();
		newnode->parent = node;
		node->children[i] = newnode;
	}

	SplitBrush(node->volume, node->planenum, &node->children[0]->volume,
		&node->children[1]->volume);

	/* recursively process children */
	for (i = 0; i < 2; i++) {
		node->children[i] = BuildTree_r(node->children[i], children[i]);
	}

	return node;
}
Exemple #13
0
static _Bool CheckPlaneAgainstVolume(int32_t pnum, node_t *node) {
	brush_t *front, *back;
	_Bool good;

	SplitBrush(node->volume, pnum, &front, &back);

	good = (front && back);

	if (front) {
		FreeBrush(front);
	}
	if (back) {
		FreeBrush(back);
	}

	return good;
}
Exemple #14
0
/*
====================
FilterBrushIntoTree_r
====================
*/
int FilterBrushIntoTree_r(bspBrush_t * b, node_t * node)
{
	bspBrush_t     *front, *back;
	int             c;

	if(!b)
	{
		return 0;
	}

	// add it to the leaf list
	if(node->planenum == PLANENUM_LEAF)
	{
		b->next = node->brushlist;
		node->brushlist = b;

		// classify the leaf by the structural brush
		if(!b->detail)
		{
			if(b->opaque)
			{
				node->opaque = qtrue;
				node->areaportal = qfalse;
			}
			else if(b->contents & CONTENTS_AREAPORTAL)
			{
				if(!node->opaque)
				{
					node->areaportal = qtrue;
				}
			}
		}

		return 1;
	}

	// split it by the node plane
	SplitBrush(b, node->planenum, &front, &back);
	FreeBrush(b);

	c = 0;
	c += FilterBrushIntoTree_r(front, node->children[0]);
	c += FilterBrushIntoTree_r(back, node->children[1]);

	return c;
}
Exemple #15
0
int FilterBrushIntoTree_r( brush_t *b, node_t *node )
{
    brush_t		*front, *back;
    int			c;

    /* dummy check */
    if( b == NULL )
        return 0;

    /* add it to the leaf list */
    if( node->planenum == PLANENUM_LEAF )
    {
        /* something somewhere is hammering brushlist */
        b->next = node->brushlist;
        node->brushlist = b;

        /* classify the leaf by the structural brush */
        if( !b->detail )
        {
            if( b->opaque )
            {
                node->opaque = qtrue;
                node->areaportal = qfalse;
            }
            else if( b->compileFlags & C_AREAPORTAL )
            {
                if( !node->opaque )
                    node->areaportal = qtrue;
            }
        }

        return 1;
    }

    /* split it by the node plane */
    c = b->numsides;
    SplitBrush( b, node->planenum, &front, &back );
    FreeBrush( b );

    c = 0;
    c += FilterBrushIntoTree_r( front, node->children[ 0 ] );
    c += FilterBrushIntoTree_r( back, node->children[ 1 ] );

    return c;
}
Exemple #16
0
node_t *BuildTree_r( node_t *node, bspbrush_t *brushes ) {
	node_t      *newnode;
	side_t      *bestside;
	int i, totalmem;
	bspbrush_t  *children[2];

	qprintf( "\r%6d", numrecurse );
	numrecurse++;

	if ( numthreads == 1 ) {
		totalmem = WindingMemory() + c_nodememory + c_brushmemory;
		if ( totalmem > c_peak_totalbspmemory ) {
			c_peak_totalbspmemory = totalmem;
		}
		c_nodes++;
	} //endif

	if ( drawflag ) {
		DrawBrushList( brushes, node );
	}

	// find the best plane to use as a splitter
	bestside = SelectSplitSide( brushes, node );
	if ( !bestside ) {
		// leaf node
		node->side = NULL;
		node->planenum = -1;
		LeafNode( node, brushes );
		if ( node->contents & CONTENTS_SOLID ) {
			c_solidleafnodes++;
		}
		if ( create_aas ) {
			//free up memory!!!
			FreeBrushList( node->brushlist );
			node->brushlist = NULL;
			//free the node volume brush
			if ( node->volume ) {
				FreeBrush( node->volume );
				node->volume = NULL;
			} //end if
		} //end if
		return node;
	} //end if

	// this is a splitplane node
	node->side = bestside;
	node->planenum = bestside->planenum & ~1;   // always use front facing

	//split the brush list in two for both children
	SplitBrushList( brushes, node, &children[0], &children[1] );
	//free the old brush list
	FreeBrushList( brushes );

	// allocate children before recursing
	for ( i = 0; i < 2; i++ )
	{
		newnode = AllocNode();
		newnode->parent = node;
		node->children[i] = newnode;
	} //end for

	//split the volume brush of the node for the children
	SplitBrush( node->volume, node->planenum, &node->children[0]->volume,
				&node->children[1]->volume );

	if ( create_aas ) {
		//free the volume brush
		if ( node->volume ) {
			FreeBrush( node->volume );
			node->volume = NULL;
		} //end if
	} //end if
	  // recursively process children
	for ( i = 0; i < 2; i++ )
	{
		node->children[i] = BuildTree_r( node->children[i], children[i] );
	} //end for

	return node;
} //end of the function BuildTree_r
Exemple #17
0
//thread function, gets nodes from the nodelist and processes them
void BuildTreeThread( int threadid ) {
	node_t *newnode, *node;
	side_t *bestside;
	int i, totalmem;
	bspbrush_t *brushes;

	for ( node = NextNodeFromList(); node; )
	{
		//if the nodelist isn't empty try to add another thread
		//if (NodeListSize() > 10) AddThread(BuildTreeThread);
		//display the number of nodes processed so far
		if ( numthreads == 1 ) {
			IncreaseNodeCounter();
		}

		brushes = node->brushlist;

		if ( numthreads == 1 ) {
			totalmem = WindingMemory() + c_nodememory + c_brushmemory;
			if ( totalmem > c_peak_totalbspmemory ) {
				c_peak_totalbspmemory = totalmem;
			} //end if
			c_nodes++;
		} //endif

		if ( drawflag ) {
			DrawBrushList( brushes, node );
		} //end if

		if ( cancelconversion ) {
			bestside = NULL;
		} //end if
		else
		{
			// find the best plane to use as a splitter
			bestside = SelectSplitSide( brushes, node );
		} //end else
		  //if there's no split side left
		if ( !bestside ) {
			//create a leaf out of the node
			LeafNode( node, brushes );
			if ( node->contents & CONTENTS_SOLID ) {
				c_solidleafnodes++;
			}

			if ( create_aas ) {
				//free up memory!!!
				FreeBrushList( node->brushlist );
				node->brushlist = NULL;
			} //end if
			  //free the node volume brush (it is not used anymore)
			if ( node->volume ) {
				FreeBrush( node->volume );
				node->volume = NULL;
			} //end if
			node = NextNodeFromList();
			continue;
		} //end if

		// this is a splitplane node
		node->side = bestside;
		node->planenum = bestside->planenum & ~1;   //always use front facing

		//allocate children
		for ( i = 0; i < 2; i++ )
		{
			newnode = AllocNode();
			newnode->parent = node;
			node->children[i] = newnode;
		} //end for

		//split the brush list in two for both children
		SplitBrushList( brushes, node, &node->children[0]->brushlist, &node->children[1]->brushlist );

		CheckBrushLists( node->children[0]->brushlist, node->children[1]->brushlist );
		//free the old brush list
		FreeBrushList( brushes );
		node->brushlist = NULL;

		//split the volume brush of the node for the children
		SplitBrush( node->volume, node->planenum, &node->children[0]->volume,
					&node->children[1]->volume );

		if ( !node->children[0]->volume || !node->children[1]->volume ) {
			Error( "child without volume brush" );
		} //end if

		//free the volume brush
		if ( node->volume ) {
			FreeBrush( node->volume );
			node->volume = NULL;
		} //end if

		//add both children to the node list
		//AddNodeToList(node->children[0]);
		AddNodeToList( node->children[1] );
		node = node->children[0];
	} //end while
	RemoveThread( threadid );
} //end of the function BuildTreeThread
Exemple #18
0
//===========================================================================
// returns a list with brushes created by splitting the given brush with
// planes that go through the face edges and are orthogonal to the face plane
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *Q1_SplitBrushWithFace(bspbrush_t *brush, q1_dface_t *face)
{
    int i, edgenum, side, planenum, splits;
    float dist;
    q1_dplane_t plane;
    vec_t *v1, *v2;
    vec3_t normal, edgevec;
    bspbrush_t *front, *back, *brushlist;

    memcpy(&plane, &q1_dplanes[face->planenum], sizeof(q1_dplane_t));
    //check on which side of the plane the face is
    if (face->side)
    {
        VectorNegate(plane.normal, plane.normal);
        plane.dist = -plane.dist;
    } //end if
    splits = 0;
    brushlist = NULL;
    for (i = 0; i < face->numedges; i++)
    {
        //get the first and second vertex of the edge
        edgenum = q1_dsurfedges[face->firstedge + i];
        side = edgenum > 0;
        //if the face plane is flipped
        v1 = q1_dvertexes[q1_dedges[abs(edgenum)].v[side]].point;
        v2 = q1_dvertexes[q1_dedges[abs(edgenum)].v[!side]].point;
        //create a plane through the edge vector, orthogonal to the face plane
        //and with the normal vector pointing out of the face
        VectorSubtract(v1, v2, edgevec);
        CrossProduct(edgevec, plane.normal, normal);
        VectorNormalize(normal);
        dist = DotProduct(normal, v1);
        //
        planenum = FindFloatPlane(normal, dist);
        //split the current brush
        SplitBrush(brush, planenum, &front, &back);
        //if there is a back brush just put it in the list
        if (back)
        {
            //copy the brush contents
            back->side = brush->side;
            //
            back->next = brushlist;
            brushlist = back;
            splits++;
        } //end if
        if (!front)
        {
            Log_Print("Q1_SplitBrushWithFace: no new brush\n");
            FreeBrushList(brushlist);
            return NULL;
        } //end if
        //copy the brush contents
        front->side = brush->side;
        //continue splitting the front brush
        brush = front;
    } //end for
    if (!splits)
    {
        FreeBrush(front);
        return NULL;
    } //end if
    front->next = brushlist;
    brushlist = front;
    return brushlist;
} //end of the function Q1_SplitBrushWithFace