예제 #1
0
void            FreePortals(node_t* node)
{
    portal_t*       p;
    portal_t*       nextp;

    if (node->planenum != -1)
    {
        FreePortals(node->children[0]);
        FreePortals(node->children[1]);
        return;
    }

    for (p = node->portals; p; p = nextp)
    {
        if (p->nodes[0] == node)
        {
            nextp = p->next[0];
        }
        else
        {
            nextp = p->next[1];
        }
        RemovePortalFromNode(p, p->nodes[0]);
        RemovePortalFromNode(p, p->nodes[1]);
        delete p->winding;
        FreePortal(p);
    }
}
예제 #2
0
//===========================================================================
//
// Parameter:			-
// Returns:				-
// Changes Globals:		-
//===========================================================================
void Tree_FreePortals_r( node_t *node ) {
	portal_t    *p, *nextp;
	int s;

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

	// free portals
	for ( p = node->portals; p; p = nextp )
	{
		s = ( p->nodes[1] == node );
		nextp = p->next[s];

		RemovePortalFromNode( p, p->nodes[!s] );
#ifdef ME
		if ( p->winding ) {
			freedtreemem += MemorySize( p->winding );
		}
		freedtreemem += MemorySize( p );
#endif //ME
		FreePortal( p );
	}
	node->portals = NULL;
} //end of the function Tree_FreePortals_r
예제 #3
0
//=====================================================================================
//	FreePOrtals_r
//=====================================================================================
geBoolean FreePortals_r(GBSP_Node *Node)
{
	GBSP_Portal *Portal, *Next;
	int32		Side;

	if (!Node)
		return GE_TRUE;
	
	for (Portal = Node->Portals; Portal; Portal = Next)
	{
		if (Portal->Nodes[0] == Node)
			Side = 0;
		else if (Portal->Nodes[1] == Node)
			Side = 1;
		else
		{
			GHook.Error("FreePortals_r:  Portal does not look at either node.\n");
			return GE_FALSE;
		}

		Next = Portal->Next[Side];

		if (!RemovePortalFromNode(Portal, Portal->Nodes[0]))
			return GE_FALSE;

		if (!RemovePortalFromNode(Portal, Portal->Nodes[1]))
			return GE_FALSE;

		if (!FreePortal(Portal))
			return GE_FALSE;
	}

	Node->Portals = NULL;

	if (Node->PlaneNum == PLANENUM_LEAF)
		return GE_TRUE;

	if (!FreePortals_r(Node->Children[0]))
		return GE_FALSE;

	if (!FreePortals_r(Node->Children[1]))
		return GE_FALSE;

	return GE_TRUE;
}
예제 #4
0
/*
==================
FreeNodePortals_r
==================
*/
static void FreeNodePortals_r (node_t *node)
{
	portal_t	*p, *nextp;

	if (!node->contents)
	{
		FreeNodePortals_r (node->children[0]);
		FreeNodePortals_r (node->children[1]);
	}

	for (p=node->portals ; p ; p=nextp)
	{
		if (p->nodes[0] == node)
			nextp = p->next[0];
		else
			nextp = p->next[1];
		RemovePortalFromNode (p, p->nodes[0]);
		RemovePortalFromNode (p, p->nodes[1]);
		FreeWinding (p->winding);
		FreePortal (p);
	}
}
예제 #5
0
파일: portals.c 프로젝트: AidHamza/eviltoys
/*
==================
FreeAllPortals

==================
*/
void
FreeAllPortals(node_t *node)
{
    portal_t *p, *nextp;

    if (!node->contents) {
	FreeAllPortals(node->children[0]);
	FreeAllPortals(node->children[1]);
    }

    for (p = node->portals; p; p = nextp) {
	if (p->nodes[0] == node)
	    nextp = p->next[0];
	else
	    nextp = p->next[1];
	RemovePortalFromNode(p, p->nodes[0]);
	RemovePortalFromNode(p, p->nodes[1]);
	FreeMem(p->winding, WINDING, 1);
	FreeMem(p, PORTAL, 1);
    }
    node->portals = NULL;
}
예제 #6
0
파일: tree.cpp 프로젝트: ibrahimmusba/ufoai
static void FreeTreePortals_r (node_t *node)
{
	portal_t *p, *nextp;

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

	/* free portals */
	for (p = node->portals; p; p = nextp) {
		const int s = (p->nodes[1] == node);
		nextp = p->next[s];

		RemovePortalFromNode(p, p->nodes[!s]);
		FreePortal(p);
	}
	node->portals = nullptr;
}
예제 #7
0
/*
   =============
   FreeTreePortals_r
   =============
 */
void FreeTreePortals_r( node_t *node ){
	portal_t    *p, *nextp;
	int s;

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

	// free portals
	for ( p = node->portals ; p ; p = nextp )
	{
		s = ( p->nodes[1] == node );
		nextp = p->next[s];

		RemovePortalFromNode( p, p->nodes[!s] );
		FreePortal( p );
	}
	node->portals = NULL;
}
예제 #8
0
//=====================================================================================
//	PartitionPortals_r
//=====================================================================================
geBoolean PartitionPortals_r(GBSP_Node *Node)
{
	GBSP_Poly		*NewPoly, *FPoly, *BPoly;
	GBSP_Plane		*pPlane, *pPlane2;
	GBSP_Portal		*Portal, *NewPortal, *Next;
	GBSP_Node		*Front, *Back, *OtherNode;
	int32			Side;

	CalcNodeBoundsFromPortals(Node);

	if (Node->PlaneNum == PLANENUM_LEAF)
		return GE_TRUE;

	if (VisPortals && Node->Detail)			// We can stop at detail seperators for the vis tree
		return GE_TRUE;

	//if (!InitializeNodePortal(Node))
	//	return GE_FALSE;
	//if (!DistributeNodePortalsToChildren(Node))
	//	return GE_FALSE;

	Front = Node->Children[0];
	Back = Node->Children[1];

	pPlane = &Planes[Node->PlaneNum];

	// Create a new portal
	if (!CreatePolyOnNode (Node, &NewPoly))
	{
		GHook.Error("PartitionPortals_r:  CreatePolyOnNode failed.\n");
		return GE_FALSE;
	}

	// Clip it against all other portals attached to this node
	for (Portal = Node->Portals; Portal && NewPoly; Portal = Portal->Next[Side])
	{
		if (Portal->Nodes[0] == Node)
			Side = 0;
		else if (Portal->Nodes[1] == Node)
			Side = 1;
		else
		{
			GHook.Error("PartitionPortals_r:  Portal does not look at either node.\n");
			return GE_FALSE;
		}

		pPlane2 = &Planes[Portal->PlaneNum];

		if (!ClipPolyEpsilon(NewPoly, 0.001f, pPlane2, Side, &NewPoly))
		{
			GHook.Error("PartitionPortals_r:  There was an error clipping the poly.\n");
			return GE_FALSE;
		}

		if (!NewPoly)
		{
			GHook.Printf("PartitionPortals_r:  Portal was cut away.\n");
			break;
		}
	}
	
	if (NewPoly && PolyIsTiny (NewPoly))
	{
		FreePoly(NewPoly);
		NewPoly = NULL;
	}

	if (NewPoly)
	{
		NewPortal = AllocPortal();
		if (!NewPortal)
		{
			GHook.Error("PartitionPortals_r:  Out of memory for portal.\n");
			return GE_FALSE;
		}
		NewPortal->Poly = NewPoly;
		NewPortal->PlaneNum = Node->PlaneNum;
		NewPortal->OnNode = Node;

		if (!CheckPortal(NewPortal))
		{
			GHook.Error("PartiionPortals_r:  Check Portal failed.\n");
			return GE_FALSE;
		}
		else
			AddPortalToNodes(NewPortal, Front, Back);

	}
	
	// Partition all portals by this node
	for (Portal = Node->Portals; Portal; Portal = Next)
	{
		if (Portal->Nodes[0] == Node)
			Side = 0;
		else if (Portal->Nodes[1] == Node)
			Side = 1;
		else
		{
			GHook.Error("PartitionPortals_r:  Portal does not look at either node.\n");
			return GE_FALSE;
		}

		Next = Portal->Next[Side];
		
		// Remember the node on the back side
		OtherNode = Portal->Nodes[!Side];
		RemovePortalFromNode(Portal, Portal->Nodes[0]);
		RemovePortalFromNode(Portal, Portal->Nodes[1]);

		if (!SplitPolyEpsilon(Portal->Poly, 0.001f, pPlane, &FPoly, &BPoly, GE_FALSE))
		{
			GHook.Error("PartitionPortals_r:  Could not split portal.\n");
			return GE_FALSE;
		}
		
		if (FPoly && PolyIsTiny(FPoly))
		{
			FreePoly(FPoly);
			FPoly = NULL;
		}

		if (BPoly && PolyIsTiny(BPoly))
		{
			FreePoly(BPoly);
			BPoly = NULL;
		}
		
		if (!FPoly && !BPoly)
			continue;
		
		if (!FPoly)
		{
			Portal->Poly = BPoly;
			if (Side)
				AddPortalToNodes(Portal, OtherNode, Back);
			else
				AddPortalToNodes(Portal, Back, OtherNode);
			continue;
		}

		if (!BPoly)
		{
			Portal->Poly = FPoly;
			if (Side)
				AddPortalToNodes(Portal, OtherNode, Front);
			else
				AddPortalToNodes(Portal, Front, OtherNode);
			continue;
		}

		// Portal was split
		NewPortal = AllocPortal();
		if (!NewPortal)
		{
			GHook.Error("PartitionPortals_r:  Out of memory for portal.\n");
			return GE_FALSE;
		}
		Portal->Poly = FPoly;
		*NewPortal = *Portal;
		NewPortal->Poly = BPoly;
		
		if (Side)
		{
			AddPortalToNodes(Portal, OtherNode, Front);
			AddPortalToNodes(NewPortal, OtherNode, Back);
		}
		else
		{
			AddPortalToNodes(Portal, Front, OtherNode);
			AddPortalToNodes(NewPortal, Back, OtherNode);
		}
	}

	if (Node->Portals != NULL)
	{
		GHook.Printf("*WARNING* PartitionPortals_r:  Portals still on node after distribution...\n");
	}
	
	if (!PartitionPortals_r(Front))
		return GE_FALSE;

	if (!PartitionPortals_r(Back))
		return GE_FALSE;

	return GE_TRUE;
}
예제 #9
0
/*
==============
SplitNodePortals

Move or split the portals that bound node so that the node's
children have portals instead of node.
==============
*/
void SplitNodePortals (node_t *node)
{
	portal_t	*p, *next_portal, *new_portal;
	node_t		*f, *b, *other_node;
	int			side;
	dplane_t	*plane;
	winding_t	*frontwinding, *backwinding;

	plane = &dplanes[node->planenum];
	f = node->children[0];
	b = node->children[1];

	for (p = node->portals ; p ; p = next_portal)	
	{
		if (p->nodes[0] == node)
			side = 0;
		else if (p->nodes[1] == node)
			side = 1;
		else
			Error ("CutNodePortals_r: mislinked portal");
		next_portal = p->next[side];

		other_node = p->nodes[!side];
		RemovePortalFromNode (p, p->nodes[0]);
		RemovePortalFromNode (p, p->nodes[1]);

//
// cut the portal into two portals, one on each side of the cut plane
//
		DivideWinding (p->winding, plane, &frontwinding, &backwinding);
		
		if (!frontwinding)
		{
			if (side == 0)
				AddPortalToNodes (p, b, other_node);
			else
				AddPortalToNodes (p, other_node, b);
			continue;
		}
		if (!backwinding)
		{
			if (side == 0)
				AddPortalToNodes (p, f, other_node);
			else
				AddPortalToNodes (p, other_node, f);
			continue;
		}
		
	// the winding is split
		new_portal = AllocPortal ();
		*new_portal = *p;
		new_portal->winding = backwinding;
		FreeWinding (p->winding);
		p->winding = frontwinding;

		if (side == 0)
		{
			AddPortalToNodes (p, f, other_node);
			AddPortalToNodes (new_portal, b, other_node);
		}
		else
		{
			AddPortalToNodes (p, other_node, f);
			AddPortalToNodes (new_portal, other_node, b);
		}
	}

	node->portals = NULL;
}
예제 #10
0
void Portal_MakeNodesRecursive( cnode_t *node, int stop_depth )
{       
	hpair_t		*pair;

//	if ( node->plane < 0 )
	if ( node->type == NodeType_leaf )
	{
		// it's a leaf
		pair = NewHPair2( "string", "portalized_leaf", "normal_leaf" );
		InsertHPair( node->self, pair );		
		portalized_num++;
		return;
	}

#if 0
	// hack: contents deep portalization
	if ( node->contents < stop_depth && node->type == NodeType_node )
	{
		pair = NewHPair2( "string", "portalized_leaf", "deep_stop" );
		InsertHPair( node->self, pair );
		portalized_num++;
		return;
	}
#endif

	if ( !Portal_MakeNodeChildren( node ) )
	{
		printf( " * Portal_MakeNodesRecursive: can't get portal for node '%s'. go up. *\n", node->self->name );
#if 1
		// test:
		// if portalization fail for a sub-tree, ignore it
		// and remove all portals, to the *node*
		{
			portal_t	*p, *next;
			int		side;

			DebugWriteNodePortals( node );
			
			for ( p = node->portals; p ; p=next )
			{
				printf( "." );
				{
					if ( p->nodes[0] == node )
						side = 0;
					else if ( p->nodes[1] == node )
						side = 1;
					else
						Error( "Portal_SplitNode: can't find node in portal.\n" );
					
					next = p->next[side];
					
					RemovePortalFromNode( p, p->nodes[0] );
					RemovePortalFromNode( p, p->nodes[1] );
					free( p );
				}
			}
		}
#endif
		pair = NewHPair2( "string", "portalized_leaf", "node_split_failed" );
		InsertHPair( node->self, pair );
		portalized_num++;
		return;
	}




	Portal_SplitNode( node );

	Portal_MakeNodesRecursive( node->child[0], stop_depth );
	Portal_MakeNodesRecursive( node->child[1], stop_depth );
}
예제 #11
0
/*
  ====================
  Portal_SplitNode

  ====================
*/
void Portal_SplitNode( cnode_t *node )
{
	cplane_t		*pl;
	portal_t		*p, *pnext;
	int		side;
	cnode_t		*othernode;
	portal_t	*frontportal, *backportal;
	polygon_t	*front, *back;

	pl = node->pl;

	side = 0;
	for ( p = node->portals; p ; p=pnext )
	{
		if ( p->nodes[0] == node )
			side = 0;
		else if ( p->nodes[1] == node )
			side = 1;
		else
			Error( "Portal_SplitNode: can't find node in portal.\n" );

		pnext = p->next[side];

		othernode = p->nodes[!side];

		RemovePortalFromNode( p, p->nodes[0] );
		RemovePortalFromNode( p, p->nodes[1] );

		SplitPolygon( p->p, pl->norm, pl->dist, &front, &back );
		FreePolygon( p->p );


		if ( !front && !back )
			Error( "Portal_SplitNode: no front and back after split.\n" );

		if ( !front )
		{
			// polygon is back
			p->p = back;

			if ( side ) // node was back of portal
				AddPortalToNodes( p, othernode, node->child[1] );
			else // node was front
				AddPortalToNodes( p, node->child[1], othernode );
			continue;
		}

		if ( !back )
		{
			// polygon is front
			p->p = front;

			if ( side ) // node was back of portal
				AddPortalToNodes( p, othernode, node->child[0] );
			else
				AddPortalToNodes( p, node->child[0], othernode );
			continue;
		}

		//
		// portal got split
		//
		frontportal = p;
		frontportal->p = front;

		backportal = NewPortal();
		memcpy( backportal, p, sizeof( portal_t ) );
		backportal->p = back;

		if ( side ) // node was back of portal
		{
			AddPortalToNodes( frontportal, othernode, node->child[0] );
			AddPortalToNodes( backportal, othernode, node->child[1] );
		}
		else
		{
			AddPortalToNodes( frontportal, node->child[0], othernode );
			AddPortalToNodes( backportal, node->child[1], othernode );
		}
	}

	node->portals = NULL;
}
예제 #12
0
/*
==============
SplitNodePortals

Move or split the portals that bound node so that the node's
children have portals instead of node.
==============
*/
void SplitNodePortals (node_t *node)
{
	portal_t	*p, *next_portal, *new_portal;
	node_t		*f, *b, *other_node;
	int			side = 0;
	plane_t		*plane;
	winding_t	*frontwinding, *backwinding;

	plane = &mapplanes[node->planenum];
	f = node->children[0];
	b = node->children[1];

	for (p = node->portals ; p ; p = next_portal)	
	{
		if (p->nodes[0] == node)
			side = 0;
		else if (p->nodes[1] == node)
			side = 1;
		else
			Error ("CutNodePortals_r: mislinked portal");
		next_portal = p->next[side];

		other_node = p->nodes[!side];
		RemovePortalFromNode (p, p->nodes[0]);
		RemovePortalFromNode (p, p->nodes[1]);

//
// cut the portal into two portals, one on each side of the cut plane
//
		ClipWindingEpsilon (p->winding, plane->normal, plane->dist,
			SPLIT_WINDING_EPSILON, &frontwinding, &backwinding);

		if (frontwinding && WindingIsTiny(frontwinding))
		{
			FreeWinding (frontwinding);
			frontwinding = NULL;
			c_tinyportals++;
		}

		if (backwinding && WindingIsTiny(backwinding))
		{
			FreeWinding (backwinding);
			backwinding = NULL;
			c_tinyportals++;
		}

		if (!frontwinding && !backwinding)
		{	// tiny windings on both sides
			continue;
		}

		if (!frontwinding)
		{
			FreeWinding (backwinding);
			if (side == 0)
				AddPortalToNodes (p, b, other_node);
			else
				AddPortalToNodes (p, other_node, b);
			continue;
		}
		if (!backwinding)
		{
			FreeWinding (frontwinding);
			if (side == 0)
				AddPortalToNodes (p, f, other_node);
			else
				AddPortalToNodes (p, other_node, f);
			continue;
		}
		
	// the winding is split
		new_portal = AllocPortal ();
		*new_portal = *p;
		new_portal->winding = backwinding;
		FreeWinding (p->winding);
		p->winding = frontwinding;

		if (side == 0)
		{
			AddPortalToNodes (p, f, other_node);
			AddPortalToNodes (new_portal, b, other_node);
		}
		else
		{
			AddPortalToNodes (p, other_node, f);
			AddPortalToNodes (new_portal, other_node, b);
		}
	}

	node->portals = NULL;
}
예제 #13
0
파일: portals.c 프로젝트: Diskutant/RTCW-SP
//===========================================================================
// Move or split the portals that bound node so that the node's
// children have portals instead of node.
//
// Parameter:               -
// Returns:                 -
// Changes Globals:     -
//===========================================================================
void SplitNodePortals(node_t *node)
{
	portal_t    *p, *next_portal, *new_portal;
	node_t *f, *b, *other_node;
	int side = 0; // TTimo: init
	plane_t *plane;
	winding_t *frontwinding, *backwinding;

	plane = &mapplanes[node->planenum];
	f = node->children[0];
	b = node->children[1];

	for(p = node->portals ; p ; p = next_portal)
	{
		if(p->nodes[0] == node)
		{
			side = 0;
		}
		else if(p->nodes[1] == node)
		{
			side = 1;
		}
		else
		{
			Error("SplitNodePortals: mislinked portal");
		}

		next_portal = p->next[side];

		other_node = p->nodes[!side];
		RemovePortalFromNode(p, p->nodes[0]);
		RemovePortalFromNode(p, p->nodes[1]);

//
// cut the portal into two portals, one on each side of the cut plane
//
		ClipWindingEpsilon(p->winding, plane->normal, plane->dist,
		                   SPLIT_WINDING_EPSILON, &frontwinding, &backwinding);

		if(frontwinding && WindingIsTiny(frontwinding))
		{
			FreeWinding(frontwinding);
			frontwinding = NULL;
			c_tinyportals++;
		} //end if

		if(backwinding && WindingIsTiny(backwinding))
		{
			FreeWinding(backwinding);
			backwinding = NULL;
			c_tinyportals++;
		} //end if

#ifdef DEBUG
		/*  //NOTE: don't use this winding ok check
		        // all the invalid windings only have a degenerate edge
		        if (frontwinding && WindingError(frontwinding))
		        {
		            Log_Print("SplitNodePortals: front %s\n", WindingErrorString());
		            FreeWinding(frontwinding);
		            frontwinding = NULL;
		        } //end if
		        if (backwinding && WindingError(backwinding))
		        {
		            Log_Print("SplitNodePortals: back %s\n", WindingErrorString());
		            FreeWinding(backwinding);
		            backwinding = NULL;
		        } //end if*/
#endif //DEBUG

		if(!frontwinding && !backwinding)      // tiny windings on both sides
		{
			continue;
		}

		if(!frontwinding)
		{
			FreeWinding(backwinding);

			if(side == 0)
			{
				AddPortalToNodes(p, b, other_node);
			}
			else
			{
				AddPortalToNodes(p, other_node, b);
			}

			continue;
		}

		if(!backwinding)
		{
			FreeWinding(frontwinding);

			if(side == 0)
			{
				AddPortalToNodes(p, f, other_node);
			}
			else
			{
				AddPortalToNodes(p, other_node, f);
			}

			continue;
		}

		// the winding is split
		new_portal = AllocPortal();
		*new_portal = *p;
		new_portal->winding = backwinding;
		FreeWinding(p->winding);
		p->winding = frontwinding;

		if(side == 0)
		{
			AddPortalToNodes(p, f, other_node);
			AddPortalToNodes(new_portal, b, other_node);
		} //end if
		else
		{
			AddPortalToNodes(p, other_node, f);
			AddPortalToNodes(new_portal, other_node, b);
		} //end else
	}

	node->portals = NULL;
} //end of the function SplitNodePortals
예제 #14
0
/*
==============
SplitNodePortals

Move or split the portals that bound node so that the node's
children have portals instead of node.
==============
*/
static void SplitNodePortals( node_t *node ) {
	uPortal_t	*p, *next_portal, *new_portal;
	node_t		*f, *b, *other_node;
	int			side;
	idPlane		*plane;
	idWinding	*frontwinding, *backwinding;
	plane = &dmapGlobals.mapPlanes[node->planenum];
	f = node->children[0];
	b = node->children[1];
	for( p = node->portals ; p ; p = next_portal ) {
		if( p->nodes[0] == node ) {
			side = 0;
		} else if( p->nodes[1] == node ) {
			side = 1;
		} else {
			common->Error( "SplitNodePortals: mislinked portal" );
			side = 0;	// quiet a compiler warning
		}
		next_portal = p->next[side];
		other_node = p->nodes[!side];
		RemovePortalFromNode( p, p->nodes[0] );
		RemovePortalFromNode( p, p->nodes[1] );
		//
		// cut the portal into two portals, one on each side of the cut plane
		//
		p->winding->Split( *plane, SPLIT_WINDING_EPSILON, &frontwinding, &backwinding );
		if( frontwinding && frontwinding->IsTiny() ) {
			delete frontwinding;
			frontwinding = NULL;
			c_tinyportals++;
		}
		if( backwinding && backwinding->IsTiny() ) {
			delete backwinding;
			backwinding = NULL;
			c_tinyportals++;
		}
		if( !frontwinding && !backwinding ) {
			// tiny windings on both sides
			continue;
		}
		if( !frontwinding ) {
			delete backwinding;
			if( side == 0 ) {
				AddPortalToNodes( p, b, other_node );
			} else {
				AddPortalToNodes( p, other_node, b );
			}
			continue;
		}
		if( !backwinding ) {
			delete frontwinding;
			if( side == 0 ) {
				AddPortalToNodes( p, f, other_node );
			} else {
				AddPortalToNodes( p, other_node, f );
			}
			continue;
		}
		// the winding is split
		new_portal = AllocPortal();
		*new_portal = *p;
		new_portal->winding = backwinding;
		delete p->winding;
		p->winding = frontwinding;
		if( side == 0 ) {
			AddPortalToNodes( p, f, other_node );
			AddPortalToNodes( new_portal, b, other_node );
		} else {
			AddPortalToNodes( p, other_node, f );
			AddPortalToNodes( new_portal, other_node, b );
		}
	}
	node->portals = NULL;
}
예제 #15
0
/*
================
CutNodePortals_r
================
*/
static void CutNodePortals_r (node_t *node)
{
	plane_t 	*plane, clipplane;
	node_t		*f, *b, *other_node;
	portal_t	*p, *new_portal, *next_portal;
	winding_t	*w, *frontwinding, *backwinding;
	int			side;

	// Vic: properly calculate the bounding box
	CalcNodeBounds (node);

	//
	// separate the portals on node into it's children
	//
	if (node->contents)
		return;			// at a leaf, no more dividing

	plane = &mapplanes[node->planenum];

	f = node->children[0];
	b = node->children[1];

	//
	// create the new portal by taking the full plane winding for the cutting plane
	// and clipping it by all of the planes from the other portals
	//
	w = BaseWindingForPlane (&mapplanes[node->planenum]);
	side = 0;	// shut up compiler warning
	for (p = node->portals ; p ; p = p->next[side])
	{
		clipplane = mapplanes[p->planenum];
		if (p->nodes[0] == node)
			side = 0;
		else if (p->nodes[1] == node)
		{
			clipplane.dist = -clipplane.dist;
			VectorNegate (clipplane.normal, clipplane.normal);
			side = 1;
		}
		else
			Error ("CutNodePortals_r: mislinked portal");

		w = ClipWinding (w, &clipplane, true);
		if (!w)
		{
			printf ("WARNING: CutNodePortals_r:new portal was clipped away\n");
			break;
		}
	}

	if (w)
	{
		// if the plane was not clipped on all sides, there was an error
		new_portal = AllocPortal ();
		new_portal->planenum = node->planenum;
		new_portal->winding = w;
		AddPortalToNodes (new_portal, f, b);
	}

	// partition the portals
	for (p = node->portals ; p ; p = next_portal)
	{
		if (p->nodes[0] == node)
			side = 0;
		else if (p->nodes[1] == node)
			side = 1;
		else
			Error ("CutNodePortals_r: mislinked portal");
		next_portal = p->next[side];

		other_node = p->nodes[!side];
		RemovePortalFromNode (p, p->nodes[0]);
		RemovePortalFromNode (p, p->nodes[1]);

		// cut the portal into two portals, one on each side of the cut plane
		DivideWindingEpsilon( p->winding, plane, &frontwinding, &backwinding, ON_EPSILON );

		if (!frontwinding)
		{
			if (side == 0)
				AddPortalToNodes (p, b, other_node);
			else
				AddPortalToNodes (p, other_node, b);
			continue;
		}
		if (!backwinding)
		{
			if (side == 0)
				AddPortalToNodes (p, f, other_node);
			else
				AddPortalToNodes (p, other_node, f);
			continue;
		}

		// the winding is split
		new_portal = AllocPortal ();
		*new_portal = *p;
		new_portal->winding = backwinding;
		FreeWinding (p->winding);
		p->winding = frontwinding;

		if (side == 0)
		{
			AddPortalToNodes (p, f, other_node);
			AddPortalToNodes (new_portal, b, other_node);
		}
		else
		{
			AddPortalToNodes (p, other_node, f);
			AddPortalToNodes (new_portal, other_node, b);
		}
	}

	CutNodePortals_r (f);
	CutNodePortals_r (b);
}
예제 #16
0
파일: portals.c 프로젝트: AidHamza/eviltoys
/*
================
CutNodePortals_r
================
*/
static void
CutNodePortals_r(node_t *node)
{
    plane_t *plane, clipplane;
    node_t *f, *b, *other_node;
    portal_t *p, *new_portal, *next_portal;
    winding_t *w, *frontwinding, *backwinding;
    int side;

#ifdef PARANOID
    CheckLeafPortalConsistancy (node);
#endif

    // separate the portals on node into it's children
    if (node->contents)
	return;			// at a leaf, no more dividing

    plane = &pPlanes[node->planenum];

    f = node->children[0];
    b = node->children[1];

    // create the new portal by taking the full plane winding for the cutting plane
    // and clipping it by all of the planes from the other portals
    new_portal = AllocMem(PORTAL, 1, true);
    new_portal->planenum = node->planenum;

    w = BaseWindingForPlane(&pPlanes[node->planenum]);
    side = 0;			// shut up compiler warning
    for (p = node->portals; p; p = p->next[side]) {
	clipplane = pPlanes[p->planenum];
	if (p->nodes[0] == node)
	    side = 0;
	else if (p->nodes[1] == node) {
	    clipplane.dist = -clipplane.dist;
	    VectorSubtract(vec3_origin, clipplane.normal, clipplane.normal);
	    side = 1;
	} else
	    Message(msgError, errMislinkedPortal);

	w = ClipWinding(w, &clipplane, true);
	if (!w) {
	    Message(msgWarning, warnPortalClippedAway);
	    break;
	}
    }

    if (w) {
	// if the plane was not clipped on all sides, there was an error
	new_portal->winding = w;
	AddPortalToNodes(new_portal, f, b);
    }
    // partition the portals
    for (p = node->portals; p; p = next_portal) {
	if (p->nodes[0] == node)
	    side = 0;
	else if (p->nodes[1] == node)
	    side = 1;
	else
	    Message(msgError, errMislinkedPortal);
	next_portal = p->next[side];

	other_node = p->nodes[!side];
	RemovePortalFromNode(p, p->nodes[0]);
	RemovePortalFromNode(p, p->nodes[1]);

	// cut the portal into two portals, one on each side of the cut plane
	DivideWinding(p->winding, plane, &frontwinding, &backwinding);

	if (!frontwinding) {
	    if (side == 0)
		AddPortalToNodes(p, b, other_node);
	    else
		AddPortalToNodes(p, other_node, b);
	    continue;
	}
	if (!backwinding) {
	    if (side == 0)
		AddPortalToNodes(p, f, other_node);
	    else
		AddPortalToNodes(p, other_node, f);
	    continue;
	}
	// the winding is split
	new_portal = AllocMem(PORTAL, 1, true);
	*new_portal = *p;
	new_portal->winding = backwinding;
	FreeMem(p->winding, WINDING, 1);
	p->winding = frontwinding;

	if (side == 0) {
	    AddPortalToNodes(p, f, other_node);
	    AddPortalToNodes(new_portal, b, other_node);
	} else {
	    AddPortalToNodes(p, other_node, f);
	    AddPortalToNodes(new_portal, other_node, b);
	}
    }

    // Display progress
    iNodesDone++;
    Message(msgPercent, iNodesDone, splitnodes);

    CutNodePortals_r(f);
    CutNodePortals_r(b);
}