Exemplo n.º 1
0
/*
================
MakeHeadnodePortals

The created portals will face the global outside_node
================
*/
void MakeHeadnodePortals (node_t *node)
{
	vec3_t		bounds[2];
	int			i, j, n;
	portal_t	*p, *portals[6];
	plane_t		bplanes[6], *pl;
	int			side;
	
	Draw_ClearWindow ();
	
// pad with some space so there will never be null volume leafs
	for (i=0 ; i<3 ; i++)
	{
		bounds[0][i] = brushset->mins[i] - SIDESPACE;
		bounds[1][i] = brushset->maxs[i] + SIDESPACE;
	}
	
	outside_node.contents = CONTENTS_SOLID;
	outside_node.portals = NULL;

	for (i=0 ; i<3 ; i++)
		for (j=0 ; j<2 ; j++)
		{
			n = j*3 + i;

			p = AllocPortal ();
			portals[n] = p;
			
			pl = &bplanes[n];
			memset (pl, 0, sizeof(*pl));
			if (j)
			{
				pl->normal[i] = -1;
				pl->dist = -bounds[j][i];
			}
			else
			{
				pl->normal[i] = 1;
				pl->dist = bounds[j][i];
			}
			p->planenum = FindPlane (pl, &side);
	
			p->winding = BaseWindingForPlane (pl);
			if (side)
				AddPortalToNodes (p, &outside_node, node);
			else
				AddPortalToNodes (p, node, &outside_node);
		}
		
// clip the basewindings by all the other planes
	for (i=0 ; i<6 ; i++)
	{
		for (j=0 ; j<6 ; j++)
		{
			if (j == i)
				continue;
			portals[i]->winding = ClipWinding (portals[i]->winding, &bplanes[j], true);
		}
	}
}
Exemplo n.º 2
0
//=====================================================================================
//	CreateOutsidePortal
//=====================================================================================
GBSP_Portal *CreateOutsidePortal(GBSP_Plane *Plane, GBSP_Node *Node)
{
	GBSP_Portal	*NewPortal;
	int32		Side;

	NewPortal = AllocPortal();
	if (!NewPortal)
		return NULL;

	NewPortal->Poly = CreatePolyFromPlane(Plane);
	if (!NewPortal->Poly)
	{
		return NULL;
	}
	NewPortal->PlaneNum = FindPlane(Plane, &Side);

	if (NewPortal->PlaneNum == -1)
	{
		GHook.Error("CreateOutsidePortal:  Could not create plane.\n");
		return NULL;
	}

	if (!Side)
	{
		if (!AddPortalToNodes(NewPortal, Node, OutsideNode))
			return NULL;
	}
	else
	{
		if (!AddPortalToNodes(NewPortal, OutsideNode, Node))
			return NULL;
	}

	return NewPortal;
}
Exemplo n.º 3
0
/*
==================
MakeNodePortal

create the new portal by taking the full plane winding for the cutting plane
and clipping it by all of parents of this node
==================
*/
static void MakeNodePortal( node_t *node ) {
	uPortal_t	*new_portal, *p;
	idWinding	*w;
	idVec3		normal;
	int			side;
	w = BaseWindingForNode( node );
	// clip the portal by all the other portals in the node
	for( p = node->portals ; p && w; p = p->next[side] ) {
		idPlane	plane;
		if( p->nodes[0] == node ) {
			side = 0;
			plane = p->plane;
		} else if( p->nodes[1] == node ) {
			side = 1;
			plane = -p->plane;
		} else {
			common->Error( "CutNodePortals_r: mislinked portal" );
			side = 0;	// quiet a compiler warning
		}
		w = w->Clip( plane, CLIP_EPSILON );
	}
	if( !w ) {
		return;
	}
	if( w->IsTiny() ) {
		c_tinyportals++;
		delete w;
		return;
	}
	new_portal = AllocPortal();
	new_portal->plane = dmapGlobals.mapPlanes[node->planenum];
	new_portal->onnode = node;
	new_portal->winding = w;
	AddPortalToNodes( new_portal, node->children[0], node->children[1] );
}
Exemplo n.º 4
0
static void MakeHeadnodePortals( tree_t *tree ) {
	idBounds	bounds;
	int			i, j, n;
	uPortal_t	*p, *portals[6];
	idPlane		bplanes[6], *pl;
	node_t *node;

	node = tree->headnode;

	tree->outside_node.planenum = PLANENUM_LEAF;
	tree->outside_node.brushlist = NULL;
	tree->outside_node.portals = NULL;
	tree->outside_node.opaque = false;

	// if no nodes, don't go any farther
	if ( node->planenum == PLANENUM_LEAF ) {
		return;
	}

	// pad with some space so there will never be null volume leafs
	for (i=0 ; i<3 ; i++) {
		bounds[0][i] = tree->bounds[0][i] - SIDESPACE;
		bounds[1][i] = tree->bounds[1][i] + SIDESPACE;
		if ( bounds[0][i] >= bounds[1][i] ) {
			common->Error( "Backwards tree volume" );
		}
	}
	
	for (i=0 ; i<3 ; i++) {
		for (j=0 ; j<2 ; j++) {
			n = j*3 + i;

			p = AllocPortal ();
			portals[n] = p;
			
			pl = &bplanes[n];
			memset (pl, 0, sizeof(*pl));
			if (j) {
				(*pl)[i] = -1;
				(*pl)[3] = bounds[j][i];
			} else {
				(*pl)[i] = 1;
				(*pl)[3] = -bounds[j][i];
			}
			p->plane = *pl;
			p->winding = new idWinding( *pl );
			AddPortalToNodes (p, node, &tree->outside_node);
		}
	}

	// clip the basewindings by all the other planes
	for (i=0 ; i<6 ; i++) {
		for (j=0 ; j<6 ; j++) {
			if (j == i) {
				continue;
			}
			portals[i]->winding = portals[i]->winding->Clip( bplanes[j], ON_EPSILON );
		}
	}
}
Exemplo n.º 5
0
void Portal_MakeHeadNode( cnode_t *n )
{
	int		i, j;
	// 6 planes
//	vec3d_t		norms[6];
//	fp_t		dists[6];
	portal_t	*portals[6];

	//
	// make outnode for tree
	//

//	tree->outnode = NewNode();
	out_node = NewNode();
	out_node->type = NodeType_outside;
	out_node->child[0] = NULL;
	out_node->child[1] = NULL;
	out_node->portals = NULL;

//	tree->outnode->contents = BRUSH_CONTENTS_EMPTY;

	for ( i = 0; i < 3; i++ )
	{
		Vec3dInit( out_planes[i].norm, 0.0, 0.0, 0.0 );
		out_planes[i].norm[i] = 1.0;
		out_planes[i].dist = BIG_BOX; //tree->max[i] + 64.0;
		out_planes[i].self = NULL;
		
		Vec3dInit( out_planes[i+3].norm, 0.0, 0.0, 0.0 );
		out_planes[i+3].norm[i] = -1.0;
		out_planes[i+3].dist = BIG_BOX; //- (tree->min[i] - 64.0);
		out_planes[i+3].self = NULL;
	}

	for ( i = 0; i < 6; i++ )
	{
		portals[i] = NewPortal();
//		Vec3dCopy( portals[i]->norm, norms[i] );
//		portals[i]->dist = dists[i];
		portals[i]->pl = &out_planes[i];

		portals[i]->p = BasePolygonForPlane( out_planes[i].norm, out_planes[i].dist );
		AddPortalToNodes( portals[i], out_node, n );
		
	}

	for ( i = 0; i < 6; i++ )
	{
		for ( j = 0; j < 6; j++ )
		{
			if( i==j )
				continue;
			if ( portals[i]->p )
				ClipPolygonInPlace( &portals[i]->p, out_planes[i].norm, out_planes[i].dist );
		}
		if ( !portals[i]->p )
			Error( "Portal_MakeHeadNode: clipped poly away.\n" );
	}	
}
Exemplo n.º 6
0
/*
 * ================
 * MakeHeadnodePortals
 * 
 * The created portals will face the global g_outside_node
 * ================
 */
void            MakeHeadnodePortals(node_t* node, const vec3_t mins, const vec3_t maxs)
{
    vec3_t          bounds[2];
    int             i, j, n;
    portal_t*       p;
    portal_t*       portals[6];
    dplane_t        bplanes[6];
    dplane_t*       pl;

    // pad with some space so there will never be null volume leafs
    for (i = 0; i < 3; i++)
    {
        bounds[0][i] = mins[i] - SIDESPACE;
        bounds[1][i] = maxs[i] + SIDESPACE;
    }

    g_outside_node.contents = CONTENTS_SOLID;
    g_outside_node.portals = NULL;

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 2; j++)
        {
            n = j * 3 + i;

            p = AllocPortal();
            portals[n] = p;

            pl = &bplanes[n];
            memset(pl, 0, sizeof(*pl));
            if (j)
            {
                pl->normal[i] = -1;
                pl->dist = -bounds[j][i];
            }
            else
            {
                pl->normal[i] = 1;
                pl->dist = bounds[j][i];
            }
            p->plane = *pl;
            p->winding = new Winding(*pl);
            AddPortalToNodes(p, node, &g_outside_node);
        }
    }

    // clip the basewindings by all the other planes
    for (i = 0; i < 6; i++)
    {
        for (j = 0; j < 6; j++)
        {
            if (j == i)
            {
                continue;
            }
            portals[i]->winding->Clip(bplanes[j], true);
        }
    }
}
Exemplo n.º 7
0
void MakeHeadnodePortals (tree_t *tree)
{
	Vector		bounds[2];
	int			i, j, n;
	portal_t	*p, *portals[6];
	plane_t		bplanes[6], *pl;
	node_t *node;

	node = tree->headnode;

// pad with some space so there will never be null volume leafs
	for (i=0 ; i<3 ; i++)
	{
		bounds[0][i] = tree->mins[i] - SIDESPACE;
		bounds[1][i] = tree->maxs[i] + SIDESPACE;
	}
	
	tree->outside_node.planenum = PLANENUM_LEAF;
	tree->outside_node.brushlist = NULL;
	tree->outside_node.portals = NULL;
	tree->outside_node.contents = 0;

	for (i=0 ; i<3 ; i++)
		for (j=0 ; j<2 ; j++)
		{
			n = j*3 + i;

			p = AllocPortal ();
			portals[n] = p;
			
			pl = &bplanes[n];
			memset (pl, 0, sizeof(*pl));
			if (j)
			{
				pl->normal[i] = -1;
				pl->dist = -bounds[j][i];
			}
			else
			{
				pl->normal[i] = 1;
				pl->dist = bounds[j][i];
			}
			p->plane = *pl;
			p->winding = BaseWindingForPlane (pl->normal, pl->dist);
			AddPortalToNodes (p, node, &tree->outside_node);
		}
		
// clip the basewindings by all the other planes
	for (i=0 ; i<6 ; i++)
	{
		for (j=0 ; j<6 ; j++)
		{
			if (j == i)
				continue;
			ChopWindingInPlace (&portals[i]->winding, bplanes[j].normal, bplanes[j].dist, ON_EPSILON);
		}
	}
}
Exemplo n.º 8
0
/*
==================
MakeNodePortal

create the new portal by taking the full plane winding for the cutting plane
and clipping it by all of parents of this node
==================
*/
void MakeNodePortal (node_t *node)
{
	portal_t	*new_portal, *p;
	winding_t	*w;
	Vector		normal;
	float		dist = 0.0f;
	int			side = 0;

	w = BaseWindingForNode (node);

	// clip the portal by all the other portals in the node
	for (p = node->portals ; p && w; p = p->next[side])	
	{
		if (p->nodes[0] == node)
		{
			side = 0;
			VectorCopy (p->plane.normal, normal);
			dist = p->plane.dist;
		}
		else if (p->nodes[1] == node)
		{
			side = 1;
			VectorSubtract (vec3_origin, p->plane.normal, normal);
			dist = -p->plane.dist;
		}
		else
		{
			Error ("CutNodePortals_r: mislinked portal");
		}

		ChopWindingInPlace (&w, normal, dist, 0.1);
	}

	if (!w)
	{
		return;
	}

	if (WindingIsTiny (w))
	{
		c_tinyportals++;
		FreeWinding (w);
		return;
	}


	new_portal = AllocPortal ();
	new_portal->plane = mapplanes[node->planenum];
	new_portal->onnode = node;
	new_portal->winding = w;	

	AddPortalToNodes (new_portal, node->children[0], node->children[1]);
}
Exemplo n.º 9
0
/*
==================
MakeNodePortal

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.

Each portal tracks the node that created it, so unused nodes
can be removed later.
==================
*/
void MakeNodePortal (node_t *node)
{
	portal_t	*new_portal, *p;
	dplane_t	*plane;
	dplane_t	clipplane;
	winding_t	*w;
	int			side;

	plane = &dplanes[node->planenum];
	w = BaseWindingForPlane (plane);

	new_portal = AllocPortal ();
	new_portal->plane = *plane;
	new_portal->onnode = node;

	side = 0;	// shut up compiler warning
	for (p = node->portals ; p ; p = p->next[side])	
	{
		clipplane = p->plane;
		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
			Error ("MakeNodePortal: mislinked portal");

		w = ClipWinding (w, &clipplane, true);
		if (!w)
		{
			printf ("WARNING: MakeNodePortal:new portal was clipped away from node@(%.0f,%.0f,%.0f)-(%.0f,%.0f,%.0f)\n",
					node->mins[0], node->mins[1], node->mins[2], 
					node->maxs[0], node->maxs[1], node->maxs[2]);
			FreePortal (new_portal);
			return;
		}
	}

	new_portal->winding = w;	
	AddPortalToNodes (new_portal, node->children[0], node->children[1]);
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
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;

#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);
}
Exemplo n.º 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;
	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;
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
0
bool_t Portal_MakeNodeChildren( cnode_t *node )
{
	cplane_t		*pl;
	polygon_t	*poly;
	portal_t	*p;

	int		side;
	portal_t	*pnew;

//	vec3d_t		norm;
//	fp_t		dist;
	cplane_t	*pln;


	if ( node->type == NodeType_leaf )
		Error( "Portal_MakeNodeChildren: oops, it's a leaf.\n" );

	pl = node->pl;

	poly = BasePolygonForPlane( pl->norm, pl->dist );

	//
	// clip polygon by all portal planes of this node
	// 

//	printf( "Portal_MakeNodeChildren: " );
	side = 0;
//	dist = 0.0;
	for ( p = node->portals; p ; p=p->next[side] )
	{	 

//		printf("*");
		if ( p->nodes[0] == node )
		{
			side = 0;
//			Vec3dFlip( norm, p->norm );
//			dist = -p->dist;

			pln = p->pl->flipplane;
		}
		else if ( p->nodes[1] == node )
		{
			side = 1;
//			Vec3dCopy( norm, p->norm );
//			dist = p->dist;
			
			pln = p->pl;
		}
		else
		{
			Error( "Portal_MakeNodeChildren: node not found in portal.\n" );		      			
		}

		if ( pl == p->pl->flipplane || pl == p->pl )
			Error( "split plane == portal plane\n" );

		if ( poly )
			ClipPolygonInPlace( &poly, pln->norm, pln->dist );
		       
	}

//	printf( "\n" );

	if ( !poly )
	{
		printf( " * Portal_MakeNodeChildren: clipped base polygon. *\n" );
		return false;
	}

	pnew = NewPortal();
	pnew->p = poly;
	pnew->pl = pl;
//	Vec3dCopy( pnew->norm, pl->norm );
//	pnew->dist = pl->dist;
//	memcpy( &pnew->plane, pl, sizeof( plane_t ) );
	AddPortalToNodes( pnew, node->child[0], node->child[1] );

	return true;
}
Exemplo n.º 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);
}
Exemplo n.º 16
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;
}
Exemplo n.º 17
0
/*
==================
MakeNodePortal

create the new portal by taking the full plane winding for the cutting plane
and clipping it by all of parents of this node
==================
*/
void MakeNodePortal (node_t *node)
{
    portal_t	*new_portal, *p;
    winding_t	*w;
    vec3_t		normal;
    float		dist;
    int			side;

    w = BaseWindingForNode (node);

    // clip the portal by all the other portals in the node
    for (p = node->portals ; p && w; p = p->next[side])
    {
        if (p->nodes[0] == node)
        {
            side = 0;
            VectorCopy (p->plane.normal, normal);
            dist = p->plane.dist;
        }
        else if (p->nodes[1] == node)
        {
            side = 1;
            VectorSubtract (vec3_origin, p->plane.normal, normal);
            dist = -p->plane.dist;
        }
        else
            Error ("CutNodePortals_r: mislinked portal");

        ChopWindingInPlace (&w, normal, dist, CLIP_EPSILON);
    }

    if (!w)
    {
        return;
    }


    /* ydnar: adding this here to fix degenerate windings */
#if 0
    if( FixWinding( w ) == qfalse )
    {
        c_badportals++;
        FreeWinding( w );
        return;
    }
#endif

    if (WindingIsTiny (w))
    {
        c_tinyportals++;
        FreeWinding (w);
        return;
    }

    new_portal = AllocPortal ();
    new_portal->plane = mapplanes[node->planenum];
    new_portal->onnode = node;
    new_portal->winding = w;
    new_portal->compileFlags = node->compileFlags;
    AddPortalToNodes (new_portal, node->children[0], node->children[1]);
}
Exemplo n.º 18
0
//===========================================================================
// 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
Exemplo n.º 19
0
void MakeNodePortal(node_t *node)
{
	portal_t    *new_portal, *p;
	winding_t   *w;
	vec3_t normal;
	float dist = 0;       // TTimo: init
	int side = 0;

	w = BaseWindingForNode(node);

	// clip the portal by all the other portals in the node
	for(p = node->portals; p && w; p = p->next[side])
	{
		if(p->nodes[0] == node)
		{
			side = 0;
			VectorCopy(p->plane.normal, normal);
			dist = p->plane.dist;
		} //end if
		else if(p->nodes[1] == node)
		{
			side = 1;
			VectorSubtract(vec3_origin, p->plane.normal, normal);
			dist = -p->plane.dist;
		} //end else if
		else
		{
			Error("MakeNodePortal: mislinked portal");
		} //end else

		ChopWindingInPlace(&w, normal, dist, 0.1);
	} //end for

	if(!w)
	{
		return;
	} //end if

	if(WindingIsTiny(w))
	{
		c_tinyportals++;
		FreeWinding(w);
		return;
	} //end if

#ifdef DEBUG
	/* //NOTE: don't use this winding ok check
	    // all the invalid windings only have a degenerate edge
	    if (WindingError(w))
	    {
	        Log_Print("MakeNodePortal: %s\n", WindingErrorString());
	        FreeWinding(w);
	        return;
	    } //end if*/
#endif //DEBUG


	new_portal = AllocPortal();
	new_portal->plane = mapplanes[node->planenum];

#ifdef ME
	new_portal->planenum = node->planenum;
#endif //ME

	new_portal->onnode = node;
	new_portal->winding = w;
	AddPortalToNodes(new_portal, node->children[0], node->children[1]);
} //end of the function MakeNodePortal
Exemplo n.º 20
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;
}