//=========================================================================== // // 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
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); } }
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; }
//=========================================================================== // // 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
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] ); } } }
/* * @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]); } }
/* * @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); } }
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
//----------------------------------------------------------------------------- // 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); } }