Beispiel #1
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void FloodPortals( node_t *firstnode ) {
	node_t *node;
	portal_t *p;
	int s;

	firstnode->occupied = 1;
	P_AddNodeToList( firstnode );

	for ( node = P_NextNodeFromList(); node; node = P_NextNodeFromList() )
	{
		for ( p = node->portals; p; p = p->next[s] )
		{
			s = ( p->nodes[1] == node );
			//if the node at the other side of the portal is occupied already
			if ( p->nodes[!s]->occupied ) {
				continue;
			}
			//if it isn't possible to flood through this portal
			if ( !Portal_EntityFlood( p, s ) ) {
				continue;
			}
			//
			p->nodes[!s]->occupied = node->occupied + 1;
			//
			P_AddNodeToList( p->nodes[!s] );
		} //end for
	} //end for
} //end of the function FloodPortals
Beispiel #2
0
void FloodAreas_r (node_t *node, portal_t *pSeeThrough)
{
	portal_t	*p;
	int			s;
	bspbrush_t	*b;
	entity_t	*e;

	if ( IsAreaportalNode(node) )
	{
		// this node is part of an area portal
		b = AreaportalBrushForNode( node );
		e = &entities[b->original->entitynum];

		// if the current area has allready touched this
		// portal, we are done
		if (e->portalareas[0] == c_areas || e->portalareas[1] == c_areas)
			return;

		// note the current area as bounding the portal
		if (e->portalareas[1])
		{
			Warning("WARNING: areaportal entity %i (brush %i) touches > 2 areas\n", b->original->entitynum, b->original->id );
			return;
		}
		
		if (e->portalareas[0])
		{
			e->portalareas[1] = c_areas;
			e->m_pPortalsLeadingIntoAreas[1] = pSeeThrough;
		}
		else
		{
			e->portalareas[0] = c_areas;
			e->m_pPortalsLeadingIntoAreas[0] = pSeeThrough;
		}

		return;
	}

	if (node->area)
		return;		// allready got it
	node->area = c_areas;

	for (p=node->portals ; p ; p = p->next[s])
	{
		s = (p->nodes[1] == node);
#if 0
		if (p->nodes[!s]->occupied)
			continue;
#endif
		if (!Portal_EntityFlood (p, s))
			continue;

		FloodAreas_r (p->nodes[!s], p);
	}
}
Beispiel #3
0
qboolean Portal_AreaLeakFlood (portal_t *p, int s)
{
	if ( !Portal_EntityFlood( p, s ) )
		return false;

	// can never cross through areaportal
	if ( (p->nodes[0]->contents & CONTENTS_AREAPORTAL)
	|| (p->nodes[1]->contents & CONTENTS_AREAPORTAL) )
		return false;

	// can flood through everything else
	return true;
}
Beispiel #4
0
//===========================================================================
//
// Parameter:				-
// Returns:					-
// Changes Globals:		-
//===========================================================================
void FloodAreas_r( node_t *node ) {
	portal_t    *p;
	int s;
	bspbrush_t  *b;
	entity_t    *e;

	if ( node->contents == CONTENTS_AREAPORTAL ) {
		// this node is part of an area portal
		b = node->brushlist;
		e = &entities[b->original->entitynum];

		// if the current area has allready touched this
		// portal, we are done
		if ( e->portalareas[0] == c_areas || e->portalareas[1] == c_areas ) {
			return;
		}

		// note the current area as bounding the portal
		if ( e->portalareas[1] ) {
			Log_Print( "WARNING: areaportal entity %i touches > 2 areas\n", b->original->entitynum );
			return;
		}
		if ( e->portalareas[0] ) {
			e->portalareas[1] = c_areas;
		} else {
			e->portalareas[0] = c_areas;
		}

		return;
	} //end if

	if ( node->area ) {
		return;     // allready got it
	}
	node->area = c_areas;

	for ( p = node->portals ; p ; p = p->next[s] )
	{
		s = ( p->nodes[1] == node );
#if 0
		if ( p->nodes[!s]->occupied ) {
			continue;
		}
#endif
		if ( !Portal_EntityFlood( p, s ) ) {
			continue;
		}

		FloodAreas_r( p->nodes[!s] );
	} //end for
} //end of the function FloodAreas_r
Beispiel #5
0
void ReportAreaportalLeak( tree_t *tree, node_t *node )
{
	portal_t *p, *pStart = NULL;
	int s;

	// Find a portal out of this areaportal into empty space
	for (p=node->portals ; p ; p = p->next[s])
	{
		s = (p->nodes[1] == node);
		if ( !Portal_EntityFlood( p, !s ) )
			continue;
		if ( p->nodes[!s]->contents & CONTENTS_AREAPORTAL )
			continue;

		pStart = p;
		break;
	}

	if ( pStart )
	{
		s = pStart->nodes[0] == node;
		Assert(!(pStart->nodes[s]->contents & CONTENTS_AREAPORTAL) );
		// flood fill the area outside this areaportal brush
		FloodAreaLeak( tree->headnode, pStart->nodes[s] );

		// find the portal into the longest path around the portal
		portal_t *pBest = NULL;
		int bestDist = 0;
		for (p=node->portals ; p ; p = p->next[s])
		{
			if ( p == pStart )
				continue;

			s = (p->nodes[1] == node);
			if ( p->nodes[!s]->occupied > bestDist )
			{
				pBest = p;
				bestDist = p->nodes[!s]->occupied;
			}
		}
		if ( pBest )
		{
			s = (pBest->nodes[0] == node);
			// write the linefile that goes from pBest to pStart
			AreaportalLeakFile( tree, pStart, pBest, pBest->nodes[s] );
		}
	}
}
Beispiel #6
0
/*
 * @brief
 */
static void FloodAreas_r(node_t * node) {
    portal_t *p;
    int32_t s;

    if (node->contents == CONTENTS_AREA_PORTAL) {
        // this node is part of an area portal
        const bsp_brush_t *b = node->brushes;
        entity_t *e = &entities[b->original->entity_num];

        // if the current area has already touched this
        // portal, we are done
        if (e->portal_areas[0] == c_areas || e->portal_areas[1] == c_areas)
            return;

        // note the current area as bounding the portal
        if (e->portal_areas[1]) {
            Com_Verbose("WARNING: areaportal entity %i touches > 2 areas\n",
                        b->original->entity_num);
            return;
        }
        if (e->portal_areas[0])
            e->portal_areas[1] = c_areas;
        else
            e->portal_areas[0] = c_areas;

        return;
    }

    if (node->area)
        return; // already got it
    node->area = c_areas;

    for (p = node->portals; p; p = p->next[s]) {
        s = (p->nodes[1] == node);
        // TODO: why is this commented out?
#if 0
        if(points->nodes[!s]->occupied)
            continue;
#endif
        if (!Portal_EntityFlood(p))
            continue;

        FloodAreas_r(p->nodes[!s]);
    }
}
Beispiel #7
0
/*
 * @brief
 */
static void FloodPortals_r(node_t * node, int32_t dist) {
    portal_t *p;
    int32_t s;

    node->occupied = dist;

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

        if (p->nodes[!s]->occupied)
            continue;

        if (!Portal_EntityFlood(p))
            continue;

        FloodPortals_r(p->nodes[!s], dist + 1);
    }
}
Beispiel #8
0
void FloodPortals_r(node_t *node, int dist)
{
	portal_t *p;
	int s;
//	int i;

	Log_Print("\r%6d", ++numrec);

	if(node->occupied)
	{
		Error("FloodPortals_r: node already occupied\n");
	}

	if(!node)
	{
		Error("FloodPortals_r: NULL node\n");
	} //end if*/

	node->occupied = dist;

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

		//if the node at the other side of the portal is occupied already
		if(p->nodes[!s]->occupied)
		{
			continue;
		}

		//if it isn't possible to flood through this portal
		if(!Portal_EntityFlood(p, s))
		{
			continue;
		}

		//flood recursively through the current portal
		FloodPortals_r(p->nodes[!s], dist + 1);
	} //end for

	Log_Print("\r%6d", --numrec);
} //end of the function FloodPortals_r
Beispiel #9
0
//-----------------------------------------------------------------------------
// Purpose: Floods outward from the given node, marking visited nodes with
//			the number of hops from a node with an entity. If we ever mark
//			the outside_node for this tree, we've leaked.
// Input  : node - 
//			dist - 
//-----------------------------------------------------------------------------
void FloodPortals_r (node_t *node, int dist)
{
	portal_t	*p;
	int			s;

	node->occupied = dist;

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

		// Skip nodes that have already been marked.
		if (p->nodes[!s]->occupied)
			continue;

		// Skip portals that lead to or from nodes with solid contents.
		if (!Portal_EntityFlood (p, s))
			continue;

		FloodPortals_r (p->nodes[!s], dist+1);
	}
}