Ejemplo n.º 1
0
static void FreeTree_r (node_t *node)
{
	face_t *f, *nextf;

	/* free children */
	if (node->planenum != PLANENUM_LEAF) {
		FreeTree_r(node->children[0]);
		FreeTree_r(node->children[1]);
	}

	/* free bspbrushes */
	FreeBrushList(node->brushlist);

	/* free faces */
	for (f = node->faces; f; f = nextf) {
		nextf = f->next;
		FreeFace(f);
	}

	/* free the node */
	if (node->volume)
		FreeBrush(node->volume);

	if (threadstate.numthreads == 1)
		c_nodes--;
	Mem_Free(node);
}
Ejemplo n.º 2
0
/*
   =============
   FreeTree_r
   =============
 */
void FreeTree_r( node_t *node ){
	face_t      *f, *nextf;

	// free children
	if ( node->planenum != PLANENUM_LEAF ) {
		FreeTree_r( node->children[0] );
		FreeTree_r( node->children[1] );
	}

	// free bspbrushes
	FreeBrushList( node->brushlist );

	// free faces
	for ( f = node->faces ; f ; f = nextf )
	{
		nextf = f->next;
		FreeFace( f );
	}

	// free the node
	if ( node->volume ) {
		FreeBrush( node->volume );
	}

	if ( numthreads == 1 ) {
		c_nodes--;
	}
	free( node );
}
Ejemplo n.º 3
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++)
	{
		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
Ejemplo n.º 4
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
tree_t *ProcessWorldBrushes( int brush_start, int brush_end ) {
	bspbrush_t *brushes;
	tree_t *tree;
	node_t *node;
	vec3_t mins, maxs;

	//take the whole world
	mins[0] = map_mins[0] - 8;
	mins[1] = map_mins[1] - 8;
	mins[2] = map_mins[2] - 8;

	maxs[0] = map_maxs[0] + 8;
	maxs[1] = map_maxs[1] + 8;
	maxs[2] = map_maxs[2] + 8;

	//reset the brush bsp
	ResetBrushBSP();

	// the makelist and chopbrushes could be cached between the passes...

	//create a list with brushes that are within the given mins/maxs
	//some brushes will be cut and only the part that falls within the
	//mins/maxs will be in the bush list
	brushes = MakeBspBrushList( brush_start, brush_end, mins, maxs );
	//

	if ( !brushes ) {
		node = AllocNode();
		node->planenum = PLANENUM_LEAF;
		node->contents = CONTENTS_SOLID;

		tree = Tree_Alloc();
		tree->headnode = node;
		VectorCopy( mins, tree->mins );
		VectorCopy( maxs, tree->maxs );
	} //end if
	else
	{
		//Carves any intersecting solid brushes into the minimum number
		//of non-intersecting brushes.
		if ( !nocsg ) {
			brushes = ChopBrushes( brushes );
			/*
			if (create_aas)
			{
				brushes = MergeBrushes(brushes);
			} //end if*/
		} //end if
		  //if the conversion is cancelled
		if ( cancelconversion ) {
			FreeBrushList( brushes );
			return NULL;
		} //end if
		  //create the actual bsp tree
		tree = BrushBSP( brushes, mins, maxs );
	} //end else
	  //return the tree
	return tree;
} //end of the function ProcessWorldBrushes
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
/*
=============
FreeTree_r
=============
*/
void FreeTree_r (node_t *node)
{
	// free children
	if (node->planenum != PLANENUM_LEAF)
	{
		FreeTree_r (node->children[0]);
		FreeTree_r (node->children[1]);
	}

	// free brushes
	FreeBrushList (node->brushlist);

	// free the node
	c_nodes--;
	Mem_Free (node);
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
//-----------------------------------------------------------------------------
// Purpose: Build faces for the detail brushes and merge them into the BSP
// Input  : *worldtree - 
//			brush_start - 
//			brush_end - 
//-----------------------------------------------------------------------------
face_t *MergeDetailTree( tree_t *worldtree, int brush_start, int brush_end )
{
	int			start;
	bspbrush_t	*detailbrushes = NULL;
	tree_t		*detailtree = NULL;
	face_t		*pFaces = NULL;
	face_t		*pLeafFaceList = NULL;

	// Grab the list of detail brushes
	detailbrushes = MakeBspBrushList (brush_start, brush_end, map_mins, map_maxs, ONLY_DETAIL );
	if (detailbrushes)
	{
		start = Plat_FloatTime();
		Msg("Chop Details...");
		// if there are detail brushes, chop them against each other
		if (!nocsg)
			detailbrushes = ChopBrushes (detailbrushes);

		Msg("done (%d)\n", (int)(Plat_FloatTime() - start) );
		// Now mark the visible sides so we can eliminate all detail brush sides
		// that are covered by other detail brush sides
		// NOTE: This still leaves detail brush sides that are covered by the world. (these are removed in the merge operation)
		Msg("Find Visible Detail Sides...");
		pFaces = ComputeVisibleBrushSides( detailbrushes );
		TryMergeFaceList( &pFaces );
		SubdivideFaceList( &pFaces );
		Msg("done (%d)\n", (int)(Plat_FloatTime() - start) );

		start = Plat_FloatTime();
		Msg("Merging details...");
		// Merge the detail solids and faces into the world tree
		// Merge all of the faces into the world tree
		pLeafFaceList = FilterFacesIntoTree( worldtree, pFaces );
		FilterBrushesIntoTree( worldtree, detailbrushes );

		FreeFaceList( pFaces );
		FreeBrushList(detailbrushes);

		Msg("done (%d)\n", (int)(Plat_FloatTime() - start) );
	}

	return pLeafFaceList;
}
Ejemplo n.º 9
0
/*
=============
FreeTree_r
=============
*/
void FreeTree_r (node_t *node)
{
	// free children
	if (node->planenum != PLANENUM_LEAF)
	{
		FreeTree_r (node->children[0]);
		FreeTree_r (node->children[1]);
	}

	// free bspbrushes
	FreeBrushList (node->brushlist);

	// free the node
	if (node->volume)
		FreeBrush (node->volume);

	if (numthreads == 1)
		c_nodes--;
	free (node);
}
Ejemplo n.º 10
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
Ejemplo n.º 11
0
//===========================================================================
// Carves any intersecting solid brushes into the minimum number
// of non-intersecting brushes.
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
bspbrush_t *ChopBrushes (bspbrush_t *head)
{
	bspbrush_t	*b1, *b2, *next;
	bspbrush_t	*tail;
	bspbrush_t	*keep;
	bspbrush_t	*sub, *sub2;
	int			c1, c2;
	int num_csg_iterations;

	Log_Print("-------- Brush CSG ---------\n");
	Log_Print("%6d original brushes\n", CountBrushList (head));

	num_csg_iterations = 0;
	qprintf("%6d output brushes", num_csg_iterations);

#if 0
	if (startbrush == 0)
		WriteBrushList ("before.gl", head, false);
#endif
	keep = NULL;

newlist:
	// find tail
	if (!head) return NULL;

	for (tail = head; tail->next; tail = tail->next)
		;

	for (b1=head ; b1 ; b1=next)
	{
		next = b1->next;

		//if the conversion is cancelled
		if (cancelconversion)
		{
			b1->next = keep;
			keep = b1;
			continue;
		} //end if
		
		for (b2 = b1->next; b2; b2 = b2->next)
		{
			if (BrushesDisjoint (b1, b2))
				continue;

			sub = NULL;
			sub2 = NULL;
			c1 = 999999;
			c2 = 999999;

			if (BrushGE (b2, b1))
			{
				sub = SubtractBrush (b1, b2);
				if (sub == b1)
				{
					continue;		// didn't really intersect
				} //end if
				if (!sub)
				{	// b1 is swallowed by b2
					head = CullList (b1, b1);
					goto newlist;
				}
				c1 = CountBrushList (sub);
			}

			if ( BrushGE (b1, b2) )
			{
				sub2 = SubtractBrush (b2, b1);
				if (sub2 == b2)
					continue;		// didn't really intersect
				if (!sub2)
				{	// b2 is swallowed by b1
					FreeBrushList (sub);
					head = CullList (b1, b2);
					goto newlist;
				}
				c2 = CountBrushList (sub2);
			}

			if (!sub && !sub2)
				continue;		// neither one can bite

			// only accept if it didn't fragment
			// (commenting this out allows full fragmentation)
			if (c1 > 1 && c2 > 1)
			{
				if (sub2)
					FreeBrushList (sub2);
				if (sub)
					FreeBrushList (sub);
				continue;
			}

			if (c1 < c2)
			{
				if (sub2) FreeBrushList (sub2);
				tail = AddBrushListToTail (sub, tail);
				head = CullList (b1, b1);
				goto newlist;
			} //end if
			else
			{
				if (sub) FreeBrushList (sub);
				tail = AddBrushListToTail (sub2, tail);
				head = CullList (b1, b2);
				goto newlist;
			} //end else
		} //end for

		if (!b2)
		{	// b1 is no longer intersecting anything, so keep it
			b1->next = keep;
			keep = b1;
		} //end if
		num_csg_iterations++;
		qprintf("\r%6d", num_csg_iterations);
	} //end for

	if (cancelconversion) return keep;
	//
	qprintf("\n");
	Log_Write("%6d output brushes\r\n", num_csg_iterations);

#if 0
	{
		WriteBrushList ("after.gl", keep, false);
		WriteBrushMap ("after.map", keep);
	}
#endif

	return keep;
} //end of the function ChopBrushes
Ejemplo n.º 12
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
Ejemplo n.º 13
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
Ejemplo n.º 14
0
/*
=================
ChopBrushes

Carves any intersecting solid brushes into the minimum number
of non-intersecting brushes. 
=================
*/
bspbrush_t *ChopBrushes (bspbrush_t *head)
{
	bspbrush_t	*b1, *b2, *next;
	bspbrush_t	*tail;
	bspbrush_t	*keep;
	bspbrush_t	*sub, *sub2;
	int			c1, c2;

	Sys_FPrintf( SYS_VRB, "---- ChopBrushes ----\n");
	Sys_FPrintf( SYS_VRB, "original brushes: %i\n", CountBrushList (head));

#if 0
	if (startbrush == 0)
		WriteBrushList ("before.gl", head, false);
#endif
	keep = NULL;

newlist:
	// find tail
	if (!head)
		return NULL;
	for (tail=head ; tail->next ; tail=tail->next)
	;

	for (b1=head ; b1 ; b1=next)
	{
		next = b1->next;
		for (b2=b1->next ; b2 ; b2 = b2->next)
		{
			if (BrushesDisjoint (b1, b2))
				continue;

			sub = NULL;
			sub2 = NULL;
			c1 = 999999;
			c2 = 999999;

			if ( BrushGE (b2, b1) )
			{
				sub = SubtractBrush (b1, b2);
				if (sub == b1)
					continue;		// didn't really intersect
				if (!sub)
				{	// b1 is swallowed by b2
					head = CullList (b1, b1);
					goto newlist;
				}
				c1 = CountBrushList (sub);
			}

			if ( BrushGE (b1, b2) )
			{
				sub2 = SubtractBrush (b2, b1);
				if (sub2 == b2)
					continue;		// didn't really intersect
				if (!sub2)
				{	// b2 is swallowed by b1
					FreeBrushList (sub);
					head = CullList (b1, b2);
					goto newlist;
				}
				c2 = CountBrushList (sub2);
			}

			if (!sub && !sub2)
				continue;		// neither one can bite

			// only accept if it didn't fragment
			// (commening this out allows full fragmentation)
			if (c1 > 1 && c2 > 1)
			{
				if (sub2)
					FreeBrushList (sub2);
				if (sub)
					FreeBrushList (sub);
				continue;
			}

			if (c1 < c2)
			{
				if (sub2)
					FreeBrushList (sub2);
				tail = AddBrushListToTail (sub, tail);
				head = CullList (b1, b1);
				goto newlist;
			}
			else
			{
				if (sub)
					FreeBrushList (sub);
				tail = AddBrushListToTail (sub2, tail);
				head = CullList (b1, b2);
				goto newlist;
			}
		}

		if (!b2)
		{	// b1 is no longer intersecting anything, so keep it
			b1->next = keep;
			keep = b1;
		}
	}

	Sys_FPrintf( SYS_VRB, "output brushes: %i\n", CountBrushList (keep));
#if 0
	{
		WriteBrushList ("after.gl", keep, false);
		WriteBrushMap ("after.map", keep);
	}
#endif
	return keep;
}