diff --git a/tools/quake3/q3map2/bsp.c b/tools/quake3/q3map2/bsp.c index 4f4c7172..a0ddafa4 100644 --- a/tools/quake3/q3map2/bsp.c +++ b/tools/quake3/q3map2/bsp.c @@ -266,6 +266,7 @@ void ProcessWorldModel( void ) xmlNodePtr polyline, leaknode; char level[ 2 ], shader[ 1024 ]; const char *value; + int leakStatus; /* sets integer blockSize from worldspawn "_blocksize" key if it exists */ value = ValueForKey( &entities[ 0 ], "_blocksize" ); @@ -314,28 +315,19 @@ void ProcessWorldModel( void ) FilterStructuralBrushesIntoTree( e, tree ); /* see if the bsp is completely enclosed */ - if( FloodEntities( tree ) || ignoreLeaks ) - { - /* rebuild a better bsp tree using only the sides that are visible from the inside */ - FillOutside( tree->headnode ); + leakStatus = FloodEntities(tree); + if (ignoreLeaks) + if(leakStatus == FLOODENTITIES_LEAKED) + leakStatus = FLOODENTITIES_GOOD; - /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */ - ClipSidesIntoTree( e, tree ); - - /* build a visible face tree */ - faces = MakeVisibleBSPFaceList( entities[ 0 ].brushes ); - FreeTree( tree ); - tree = FaceBSP( faces ); - MakeTreePortals( tree ); - FilterStructuralBrushesIntoTree( e, tree ); + if ( leakStatus == FLOODENTITIES_GOOD ) + { leaked = qfalse; - - /* ydnar: flood again for skybox */ - if( skyboxPresent ) - FloodEntities( tree ); } else { + leaked = qtrue; + Sys_FPrintf( SYS_NOXML, "**********************\n" ); Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" ); Sys_FPrintf( SYS_NOXML, "**********************\n" ); @@ -352,10 +344,26 @@ void ProcessWorldModel( void ) Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n"); exit( 0 ); } - leaked = qtrue; - + } + + if(leakStatus != FLOODENTITIES_EMPTY) /* if no entities exist, this would accidentally the whole map, and that IS bad */ + { + /* rebuild a better bsp tree using only the sides that are visible from the inside */ + FillOutside( tree->headnode ); + /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */ ClipSidesIntoTree( e, tree ); + + /* build a visible face tree (same thing as the initial bsp tree but after reducing the faces) */ + faces = MakeVisibleBSPFaceList( entities[ 0 ].brushes ); + FreeTree( tree ); + tree = FaceBSP( faces ); + MakeTreePortals( tree ); + FilterStructuralBrushesIntoTree( e, tree ); + + /* ydnar: flood again for skybox */ + if( skyboxPresent ) + FloodEntities( tree ); } /* save out information for visibility processing */ diff --git a/tools/quake3/q3map2/portals.c b/tools/quake3/q3map2/portals.c index e16c12c7..e3fc635b 100644 --- a/tools/quake3/q3map2/portals.c +++ b/tools/quake3/q3map2/portals.c @@ -585,9 +585,26 @@ void FloodPortals_r( node_t *node, int dist, qboolean skybox ) if( skybox ) node->skybox = skybox; - - if( node->occupied || node->opaque ) + + if( node->opaque) return; + + if( node->occupied ) + { + if( node->occupied > dist ) + { + /* reduce distance! */ + /* for better leak line */ + /* note: node->occupied will also be true for all further nodes, then */ + node->occupied = dist; + for( p = node->portals; p; p = p->next[ s ] ) + { + s = (p->nodes[ 1 ] == node); + FloodPortals_r( p->nodes[ !s ], dist + 1, skybox ); + } + } + return; + } c_floodedleafs++; node->occupied = dist; @@ -644,14 +661,15 @@ Marks all nodes that can be reached by entites ============= */ -qboolean FloodEntities( tree_t *tree ) +int FloodEntities( tree_t *tree ) { int i, s; vec3_t origin, offset, scale, angles; - qboolean r, inside, tripped, skybox; + qboolean r, inside, skybox; node_t *headnode; - entity_t *e; + entity_t *e, *tripped; const char *value; + int tripcount; headnode = tree->headnode; @@ -729,21 +747,33 @@ qboolean FloodEntities( tree_t *tree ) { Sys_Printf( "Entity %i, Brush %i: Entity in solid\n", e->mapEntityNum, 0); } - else if( tree->outside_node.occupied && !tripped ) + else if( tree->outside_node.occupied ) { - xml_Select( "Entity leaked", e->mapEntityNum, 0, qfalse ); - tripped = qtrue; + if(!tripped || tree->outside_node.occupied < tripcount) + { + tripped = e; + tripcount = tree->outside_node.occupied; + } } } + + if(tripped) + xml_Select( "Entity leaked", e->mapEntityNum, 0, qfalse ); Sys_FPrintf( SYS_VRB, "%9d flooded leafs\n", c_floodedleafs ); if( !inside ) + { Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n" ); - else if( tree->outside_node.occupied ) - Sys_FPrintf( SYS_VRB, "entity reached from outside -- no filling\n" ); + return FLOODENTITIES_EMPTY; + } + if( tree->outside_node.occupied ) + { + Sys_FPrintf( SYS_VRB, "entity reached from outside -- leak detected\n" ); + return FLOODENTITIES_LEAKED; + } - return (qboolean) (inside && !tree->outside_node.occupied); + return FLOODENTITIES_GOOD; } /* diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h index f4b88d7a..49cdd11d 100644 --- a/tools/quake3/q3map2/q3map2.h +++ b/tools/quake3/q3map2/q3map2.h @@ -1598,7 +1598,10 @@ void SplitNodePortals( node_t *node ); qboolean PortalPassable( portal_t *p ); -qboolean FloodEntities( tree_t *tree ); +#define FLOODENTITIES_LEAKED 1 +#define FLOODENTITIES_GOOD 0 +#define FLOODENTITIES_EMPTY -1 +int FloodEntities( tree_t *tree ); void FillOutside( node_t *headnode); void FloodAreas( tree_t *tree); face_t *VisibleFaces( entity_t *e, tree_t *tree );