Merge remote-tracking branch 'origin/divVerent/leak-fix'

This commit is contained in:
Rudolf Polzer 2012-02-19 18:40:59 +01:00
commit e8f94f12dd
3 changed files with 72 additions and 31 deletions

View File

@ -266,6 +266,7 @@ void ProcessWorldModel( void )
xmlNodePtr polyline, leaknode; xmlNodePtr polyline, leaknode;
char level[ 2 ], shader[ 1024 ]; char level[ 2 ], shader[ 1024 ];
const char *value; const char *value;
int leakStatus;
/* sets integer blockSize from worldspawn "_blocksize" key if it exists */ /* sets integer blockSize from worldspawn "_blocksize" key if it exists */
value = ValueForKey( &entities[ 0 ], "_blocksize" ); value = ValueForKey( &entities[ 0 ], "_blocksize" );
@ -314,28 +315,19 @@ void ProcessWorldModel( void )
FilterStructuralBrushesIntoTree( e, tree ); FilterStructuralBrushesIntoTree( e, tree );
/* see if the bsp is completely enclosed */ /* see if the bsp is completely enclosed */
if( FloodEntities( tree ) || ignoreLeaks ) leakStatus = FloodEntities(tree);
{ if (ignoreLeaks)
/* rebuild a better bsp tree using only the sides that are visible from the inside */ if(leakStatus == FLOODENTITIES_LEAKED)
FillOutside( tree->headnode ); leakStatus = FLOODENTITIES_GOOD;
/* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */ if ( leakStatus == FLOODENTITIES_GOOD )
ClipSidesIntoTree( e, tree ); {
/* build a visible face tree */
faces = MakeVisibleBSPFaceList( entities[ 0 ].brushes );
FreeTree( tree );
tree = FaceBSP( faces );
MakeTreePortals( tree );
FilterStructuralBrushesIntoTree( e, tree );
leaked = qfalse; leaked = qfalse;
/* ydnar: flood again for skybox */
if( skyboxPresent )
FloodEntities( tree );
} }
else else
{ {
leaked = qtrue;
Sys_FPrintf( SYS_NOXML, "**********************\n" ); Sys_FPrintf( SYS_NOXML, "**********************\n" );
Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" ); Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
Sys_FPrintf( SYS_NOXML, "**********************\n" ); Sys_FPrintf( SYS_NOXML, "**********************\n" );
@ -352,10 +344,26 @@ void ProcessWorldModel( void )
Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n"); Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
exit( 0 ); 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 */ /* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
ClipSidesIntoTree( e, tree ); 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 */ /* save out information for visibility processing */

View File

@ -585,9 +585,26 @@ void FloodPortals_r( node_t *node, int dist, qboolean skybox )
if( skybox ) if( skybox )
node->skybox = skybox; node->skybox = skybox;
if( node->occupied || node->opaque ) if( node->opaque)
return; 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++; c_floodedleafs++;
node->occupied = dist; 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; int i, s;
vec3_t origin, offset, scale, angles; vec3_t origin, offset, scale, angles;
qboolean r, inside, tripped, skybox; qboolean r, inside, skybox;
node_t *headnode; node_t *headnode;
entity_t *e; entity_t *e, *tripped;
const char *value; const char *value;
int tripcount;
headnode = tree->headnode; 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); 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 ); if(!tripped || tree->outside_node.occupied < tripcount)
tripped = qtrue; {
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 ); Sys_FPrintf( SYS_VRB, "%9d flooded leafs\n", c_floodedleafs );
if( !inside ) if( !inside )
{
Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n" ); Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n" );
else if( tree->outside_node.occupied ) return FLOODENTITIES_EMPTY;
Sys_FPrintf( SYS_VRB, "entity reached from outside -- no filling\n" ); }
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;
} }
/* /*

View File

@ -1598,7 +1598,10 @@ void SplitNodePortals( node_t *node );
qboolean PortalPassable( portal_t *p ); 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 FillOutside( node_t *headnode);
void FloodAreas( tree_t *tree); void FloodAreas( tree_t *tree);
face_t *VisibleFaces( entity_t *e, tree_t *tree ); face_t *VisibleFaces( entity_t *e, tree_t *tree );