* discard excess portals in the void (great optimization for maps with void areas in between of playable areas and non rectangular maps)

(excess portals there are effect of _blocksize)
	* optimize FloodPortals() (also fix stack depth crash in debug mode due to recursive calls)
	* fix xml_Select() of leaked entity (was selecting last map entity always)
	* xml_Select() leaked entity exactly in the beginning of leak line
This commit is contained in:
Garux 2021-02-06 22:14:27 +03:00
parent e729f7b898
commit 5fd7b340df
4 changed files with 42 additions and 68 deletions

View File

@ -378,10 +378,9 @@ void ProcessWorldModel( void ){
exit( 0 ); exit( 0 );
} }
/* ydnar: flood again for skybox */ /* flood again to discard portals in the void (also required for _skybox) */
if ( skyboxPresent ) {
FloodEntities( tree ); FloodEntities( tree );
} FillOutside( tree->headnode );
} }
/* save out information for visibility processing */ /* save out information for visibility processing */

View File

@ -117,5 +117,7 @@ xmlNodePtr LeakFile( tree_t *tree ){
fclose( linefile ); fclose( linefile );
xml_Select( "Entity leaked", node->occupant->mapEntityNum, 0, false );
return xml_node; return xml_node;
} }

View File

@ -547,47 +547,35 @@ void MakeTreePortals( tree_t *tree ){
int c_floodedleafs; int c_floodedleafs;
/* void FloodPortals( node_t *node, bool skybox ){
============= int dist = 1;
FloodPortals_r std::vector<node_t*> nodes{ node };
============= while( !nodes.empty() ){
*/ std::vector<node_t*> nodes2;
for( node_t *n : nodes ){
void FloodPortals_r( node_t *node, int dist, bool skybox ){
int s;
portal_t *p;
if ( skybox ) { if ( skybox ) {
node->skybox = skybox; n->skybox = skybox;
} }
if ( node->opaque ) { if ( n->opaque || ( n->occupied && n->occupied <= dist ) ) { // also reprocess occupied nodes for shorter leak line
return; continue;
} }
if ( node->occupied ) { if( !n->occupied ){
if ( node->occupied > dist ) { ++c_floodedleafs;
/* reduce distance! */ }
/* for better leak line */
/* note: node->occupied will also be true for all further nodes, then */ n->occupied = dist;
node->occupied = dist;
for ( p = node->portals; p; p = p->next[ s ] ) int s;
for ( portal_t *p = n->portals; p; p = p->next[ s ] )
{ {
s = ( p->nodes[ 1 ] == node ); s = ( p->nodes[ 1 ] == n );
FloodPortals_r( p->nodes[ !s ], dist + 1, skybox ); nodes2.push_back( p->nodes[ !s ] );
} }
} }
return; nodes.swap( nodes2 );
} ++dist;
c_floodedleafs++;
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 );
} }
} }
@ -599,7 +587,7 @@ void FloodPortals_r( node_t *node, int dist, bool skybox ){
============= =============
*/ */
bool PlaceOccupant( node_t *headnode, vec3_t origin, entity_t *occupant, bool skybox ){ bool PlaceOccupant( node_t *headnode, vec3_t origin, const entity_t *occupant, bool skybox ){
vec_t d; vec_t d;
node_t *node; node_t *node;
plane_t *plane; plane_t *plane;
@ -625,7 +613,7 @@ bool PlaceOccupant( node_t *headnode, vec3_t origin, entity_t *occupant, bool sk
node->occupant = occupant; node->occupant = occupant;
node->skybox = skybox; node->skybox = skybox;
FloodPortals_r( node, 1, skybox ); FloodPortals( node, skybox );
return true; return true;
} }
@ -641,9 +629,7 @@ bool PlaceOccupant( node_t *headnode, vec3_t origin, entity_t *occupant, bool sk
int FloodEntities( tree_t *tree ){ int FloodEntities( tree_t *tree ){
bool r, inside, skybox; bool r, inside, skybox;
node_t *headnode; node_t *headnode;
entity_t *e, *tripped;
const char *value; const char *value;
int tripcount = INT_MIN;
headnode = tree->headnode; headnode = tree->headnode;
@ -651,31 +637,29 @@ int FloodEntities( tree_t *tree ){
inside = false; inside = false;
tree->outside_node.occupied = 0; tree->outside_node.occupied = 0;
tripped = NULL;
c_floodedleafs = 0; c_floodedleafs = 0;
for ( std::size_t i = 1; i < entities.size(); ++i ) for ( std::size_t i = 1; i < entities.size(); ++i )
{ {
/* get entity */ /* get entity */
e = &entities[ i ]; const entity_t& e = entities[ i ];
/* get origin */ /* get origin */
vec3_t origin; vec3_t origin;
e->vectorForKey( "origin", origin ); e.vectorForKey( "origin", origin );
#if 0 //allow maps with only point entity@( 0, 0, 0 ); assuming that entities, containing no primitives are point ones #if 0 // 0 = allow maps with only point entity@( 0, 0, 0 ); assuming that entities, containing no primitives are point ones
/* as a special case, allow origin-less entities */ /* as a special case, allow origin-less entities */
if ( VectorCompare( origin, vec3_origin ) ) { if ( VectorCompare( origin, vec3_origin ) ) {
continue; continue;
} }
#endif #endif
/* also allow bmodel entities outside, as they could be on a moving path that will go into the map */ /* also allow bmodel entities outside, as they could be on a moving path that will go into the map */
if ( e->brushes != NULL || e->patches != NULL || e->classname_is( "_decal" ) ) { //_decal primitive is freed at this point if ( e.brushes != NULL || e.patches != NULL || e.classname_is( "_decal" ) ) { //_decal primitive is freed at this point
continue; continue;
} }
/* handle skybox entities */ /* handle skybox entities */
if ( e->classname_is( "_skybox" ) ) { if ( e.classname_is( "_skybox" ) ) {
skybox = true; skybox = true;
skyboxPresent = true;
/* invert origin */ /* invert origin */
vec3_t offset; vec3_t offset;
@ -683,15 +667,15 @@ int FloodEntities( tree_t *tree ){
/* get scale */ /* get scale */
vec3_t scale = { 64.0f, 64.0f, 64.0f }; vec3_t scale = { 64.0f, 64.0f, 64.0f };
if( !e->read_keyvalue( scale, "_scale" ) ) if( !e.read_keyvalue( scale, "_scale" ) )
if( e->read_keyvalue( scale[0], "_scale" ) ) if( e.read_keyvalue( scale[0], "_scale" ) )
scale[1] = scale[2] = scale[0]; scale[1] = scale[2] = scale[0];
/* get "angle" (yaw) or "angles" (pitch yaw roll), store as (roll pitch yaw) */ /* get "angle" (yaw) or "angles" (pitch yaw roll), store as (roll pitch yaw) */
vec3_t angles = { 0.f, 0.f, 0.f }; vec3_t angles = { 0.f, 0.f, 0.f };
if ( !e->read_keyvalue( value, "angles" ) || if ( !e.read_keyvalue( value, "angles" ) ||
3 != sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] ) ) 3 != sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] ) )
e->read_keyvalue( angles[ 2 ], "angle" ); e.read_keyvalue( angles[ 2 ], "angle" );
/* set transform matrix (thanks spog) */ /* set transform matrix (thanks spog) */
m4x4_identity( skyboxTransform ); m4x4_identity( skyboxTransform );
@ -709,23 +693,13 @@ int FloodEntities( tree_t *tree ){
//% origin[ 2 ] += 4096; //% origin[ 2 ] += 4096;
/* find leaf */ /* find leaf */
r = PlaceOccupant( headnode, origin, e, skybox ); r = PlaceOccupant( headnode, origin, &e, skybox );
if ( r ) { if ( r ) {
inside = true; inside = true;
} }
if ( !r ) { else {
Sys_FPrintf( SYS_WRN, "Entity %i (%s): Entity in solid\n", e->mapEntityNum, e->classname() ); Sys_FPrintf( SYS_WRN, "Entity %i (%s): Entity in solid\n", e.mapEntityNum, e.classname() );
} }
else if ( tree->outside_node.occupied ) {
if ( !tripped || tree->outside_node.occupied < tripcount ) {
tripped = e;
tripcount = tree->outside_node.occupied;
}
}
}
if ( tripped ) {
xml_Select( "Entity leaked", e->mapEntityNum, 0, false );
} }
Sys_FPrintf( SYS_VRB, "%9d flooded leafs\n", c_floodedleafs ); Sys_FPrintf( SYS_VRB, "%9d flooded leafs\n", c_floodedleafs );

View File

@ -1115,7 +1115,7 @@ struct node_t
drawSurfRef_t *drawSurfReferences; drawSurfRef_t *drawSurfReferences;
int occupied; /* 1 or greater can reach entity */ int occupied; /* 1 or greater can reach entity */
entity_t *occupant; /* for leak file testing */ const entity_t *occupant; /* for leak file testing */
struct portal_t *portals; /* also on nodes during construction */ struct portal_t *portals; /* also on nodes during construction */
@ -2132,7 +2132,6 @@ Q_EXTERN byte debugColors[ 12 ][ 3 ]
}; };
#endif #endif
Q_EXTERN bool skyboxPresent Q_ASSIGN( false );
Q_EXTERN int skyboxArea Q_ASSIGN( -1 ); Q_EXTERN int skyboxArea Q_ASSIGN( -1 );
Q_EXTERN m4x4_t skyboxTransform; Q_EXTERN m4x4_t skyboxTransform;