/* * @brief Marks all nodes that can be reached by entites */ _Bool FloodEntities(tree_t *tree) { int32_t i; vec3_t origin; const char *cl; _Bool inside; node_t *head_node; head_node = tree->head_node; Com_Debug("--- FloodEntities ---\n"); inside = false; tree->outside_node.occupied = 0; cl = ""; for (i = 1; i < num_entities; i++) { GetVectorForKey(&entities[i], "origin", origin); if (VectorCompare(origin, vec3_origin)) continue; cl = ValueForKey(&entities[i], "classname"); origin[2] += 1; // so objects on floor are ok // nudge playerstart around if needed so clipping hulls always // have a valid point if (!g_strcmp0(cl, "info_player_start")) { int32_t x, y; for (x = -16; x <= 16; x += 16) { for (y = -16; y <= 16; y += 16) { origin[0] += x; origin[1] += y; if (PlaceOccupant(head_node, origin, &entities[i])) { inside = true; goto gotit; } origin[0] -= x; origin[1] -= y; } } gotit: ; } else { if (PlaceOccupant(head_node, origin, &entities[i])) inside = true; } } if (!inside) { Com_Debug("no entities in open -- no filling\n"); } else if (tree->outside_node.occupied) { Com_Debug("entity %s reached from outside -- no filling\n", cl); } return inside && !tree->outside_node.occupied; }
/* =========== FillOutside =========== */ node_t *FillOutside (node_t *node, qboolean leakfile) { int s; vec_t *v; int i; qboolean inside; qboolean ret; vec3_t origin; char *cl; qprintf ("----- FillOutside ----\n"); if (nofill) { printf ("skipped\n"); return node; } // // place markers for all entities so // we know if we leak inside // inside = false; for (i=1 ; i<num_entities ; i++) { GetVectorForKey (&entities[i], "origin", origin); if (!VectorCompare(origin, vec3_origin)) { cl = ValueForKey (&entities[i], "classname"); origin[2] += 1; // so objects on floor are ok // nudge playerstart around if needed so clipping hulls allways // have a vlaid point if (!strcmp (cl, "info_player_start")) { int x, y; for (x=-16 ; x<=16 ; x += 16) { for (y=-16 ; y<=16 ; y += 16) { origin[0] += x; origin[1] += y; if (PlaceOccupant (i, origin, node)) { inside = true; goto gotit; } origin[0] -= x; origin[1] -= y; } } gotit: ; } else { if (PlaceOccupant (i, origin, node)) inside = true; } } } if (!inside) { printf ("Hullnum %i: No entities in empty space -- no filling performed\n", hullnum); return node; } s = !(outside_node.portals->nodes[1] == &outside_node); // first check to see if an occupied leaf is hit outleafs = 0; valid++; prevleaknode = NULL; if (leakfile) { pointfile = fopen (pointfilename, "w"); if (!pointfile) Error ("Couldn't open %s\n", pointfilename); StripExtension (pointfilename); strcat (pointfilename, ".lin"); linefile = fopen (pointfilename, "w"); if (!linefile) Error ("Couldn't open %s\n", pointfilename); } ret = RecursiveFillOutside (outside_node.portals->nodes[s], false); if (leakfile) { fclose (pointfile); fclose (linefile); } if (ret) { printf("LEAK LEAK LEAK\n"); GetVectorForKey (&entities[hit_occupied], "origin", origin); qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n" , origin[0], origin[1], origin[2]); qprintf ("no filling performed\n"); qprintf ("point file and line file generated\n"); qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); if (leakonly) Error ("Stopped by leak."); return node; } // now go back and fill things in valid++; RecursiveFillOutside (outside_node.portals->nodes[s], true); // remove faces and nodes from filled in leafs c_falsenodes = 0; c_free_faces = 0; c_keep_faces = 0; node = ClearOutFaces_r (node); qprintf ("%5i outleafs\n", outleafs); qprintf ("%5i freed faces\n", c_free_faces); qprintf ("%5i keep faces\n", c_keep_faces); qprintf ("%5i falsenodes\n", c_falsenodes); // save portal file for vis tracing if (leakfile) WritePortalfile (node); return node; }
/* =========== FillOutside =========== */ qboolean FillOutside (node_t *node) { int s; vec_t *v; int i; qboolean inside; qprintf ("----- FillOutside ----\n"); if (nofill) { printf ("skipped\n"); return false; } inside = false; for (i=1 ; i<num_entities ; i++) { if (!VectorCompare(entities[i].origin, vec3_origin)) { if (PlaceOccupant (i, entities[i].origin, node)) inside = true; } } if (!inside) { printf ("Hullnum %i: No entities in empty space -- no filling performed\n", hullnum); return false; } s = !(outside_node.portals->nodes[1] == &outside_node); // first check to see if an occupied leaf is hit outleafs = 0; valid++; prevleaknode = NULL; if (!hullnum) { leakfile = fopen (pointfilename, "w"); if (!leakfile) Error ("Couldn't open %s\n", pointfilename); } if (RecursiveFillOutside (outside_node.portals->nodes[s], false)) { v = entities[hit_occupied].origin; qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n" , v[0], v[1], v[2]); qprintf ("no filling performed\n"); if (!hullnum) fclose (leakfile); qprintf ("leak file written to %s\n", pointfilename); qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); return false; } if (!hullnum) fclose (leakfile); // now go back and fill things in valid++; RecursiveFillOutside (outside_node.portals->nodes[s], true); // remove faces from filled in leafs ClearOutFaces (node); qprintf ("%4i outleafs\n", outleafs); return true; }
//=========================================================================== // Marks all nodes that can be reached by entites // // Parameter: - // Returns: - // Changes Globals: - //=========================================================================== qboolean FloodEntities(tree_t *tree) { int i; int x, y; vec3_t origin; char *cl; qboolean inside; node_t *headnode; headnode = tree->headnode; Log_Print("------ FloodEntities -------\n"); inside = false; tree->outside_node.occupied = 0; //start at entity 1 not the world ( = 0) for(i = 1; i < num_entities; i++) { GetVectorForKey(&entities[i], "origin", origin); if(VectorCompare(origin, vec3_origin)) { continue; } cl = ValueForKey(&entities[i], "classname"); origin[2] += 1; //so objects on floor are ok // Log_Print("flooding from entity %d: %s\n", i, cl); //nudge playerstart around if needed so clipping hulls allways //have a valid point if(!strcmp(cl, "info_player_start")) { for(x = -16; x <= 16; x += 16) { for(y = -16; y <= 16; y += 16) { origin[0] += x; origin[1] += y; if(PlaceOccupant(headnode, origin, &entities[i])) { inside = true; x = 999; //stop for this info_player_start break; } //end if origin[0] -= x; origin[1] -= y; } //end for } //end for } //end if else { if(PlaceOccupant(headnode, origin, &entities[i])) { inside = true; } //end if } //end else } //end for if(!inside) { Log_Print("WARNING: no entities inside\n"); } //end if else if(tree->outside_node.occupied) { Log_Print("WARNING: entity reached from outside\n"); } //end else if return (qboolean)(inside && !tree->outside_node.occupied); } //end of the function FloodEntities
/* ============= FloodEntities Marks all nodes that can be reached by entites ============= */ bool FloodEntities( tree_t *tree ) { int i; idVec3 origin; const char *cl; bool inside; node_t *headnode; headnode = tree->headnode; common->Printf( "--- FloodEntities ---\n" ); inside = false; tree->outside_node.occupied = 0; c_floodedleafs = 0; bool errorShown = false; for( i = 1 ; i < dmapGlobals.num_entities ; i++ ) { idMapEntity *mapEnt; mapEnt = dmapGlobals.uEntities[i].mapEntity; if( !mapEnt->epairs.GetVector( "origin", "", origin ) ) { continue; } // any entity can have "noFlood" set to skip it if( mapEnt->epairs.GetString( "noFlood", "", &cl ) ) { continue; } mapEnt->epairs.GetString( "classname", "", &cl ); if( !strcmp( cl, "light" ) ) { const char *v; // don't place lights that have a light_start field, because they can still // be valid if their origin is outside the world mapEnt->epairs.GetString( "light_start", "", &v ); if( v[0] ) { continue; } // don't place fog lights, because they often // have origins outside the light mapEnt->epairs.GetString( "texture", "", &v ); if( v[0] ) { const idMaterial *mat = declManager->FindMaterial( v ); if( mat->IsFogLight() ) { continue; } } } if( PlaceOccupant( headnode, origin, &dmapGlobals.uEntities[i] ) ) { inside = true; } if( tree->outside_node.occupied && !errorShown ) { errorShown = true; common->Printf( "Leak on entity # %d\n", i ); const char *p; mapEnt->epairs.GetString( "classname", "", &p ); common->Printf( "Entity classname was: %s\n", p ); mapEnt->epairs.GetString( "name", "", &p ); common->Printf( "Entity name was: %s\n", p ); idVec3 origin; if( mapEnt->epairs.GetVector( "origin", "", origin ) ) { common->Printf( "Entity origin is: %f %f %f\n\n\n", origin.x, origin.y, origin.z ); } } } common->Printf( "%5i flooded leafs\n", c_floodedleafs ); if( !inside ) { common->Printf( "no entities in open -- no filling\n" ); } else if( tree->outside_node.occupied ) { common->Printf( "entity reached from outside -- no filling\n" ); } return ( bool )( inside && !tree->outside_node.occupied ); }
qboolean FloodEntities( tree_t *tree ) { int i, s; vec3_t origin, offset, scale, angles; qboolean r, inside, tripped, skybox; node_t *headnode; entity_t *e; const char *value; headnode = tree->headnode; Sys_FPrintf( SYS_VRB,"--- FloodEntities ---\n" ); inside = qfalse; tree->outside_node.occupied = 0; tripped = qfalse; c_floodedleafs = 0; for( i = 1; i < numEntities; i++ ) { /* get entity */ e = &entities[ i ]; /* get origin */ GetVectorForKey( e, "origin", origin ); if( VectorCompare( origin, vec3_origin ) ) continue; /* handle skybox entities */ value = ValueForKey( e, "classname" ); if( !Q_stricmp( value, "_skybox" ) ) { skybox = qtrue; skyboxPresent = qtrue; /* invert origin */ VectorScale( origin, -1.0f, offset ); /* get scale */ VectorSet( scale, 64.0f, 64.0f, 64.0f ); value = ValueForKey( e, "_scale" ); if( value[ 0 ] != '\0' ) { s = sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] ); if( s == 1 ) { scale[ 1 ] = scale[ 0 ]; scale[ 2 ] = scale[ 0 ]; } } /* get "angle" (yaw) or "angles" (pitch yaw roll) */ VectorClear( angles ); angles[ 2 ] = FloatForKey( e, "angle" ); value = ValueForKey( e, "angles" ); if( value[ 0 ] != '\0' ) sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] ); /* set transform matrix (thanks spog) */ m4x4_identity( skyboxTransform ); m4x4_pivoted_transform_by_vec3( skyboxTransform, offset, angles, eXYZ, scale, origin ); } else skybox = qfalse; /* nudge off floor */ origin[ 2 ] += 1; /* debugging code */ //% if( i == 1 ) //% origin[ 2 ] += 4096; /* find leaf */ r = PlaceOccupant( headnode, origin, e, skybox ); if( r ) inside = qtrue; if( (!r || tree->outside_node.occupied) && !tripped ) { xml_Select( "Entity leaked", e->mapEntityNum, 0, qfalse ); tripped = qtrue; } } 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 (qboolean) (inside && !tree->outside_node.occupied); }
/* =========== FillOutside =========== */ qboolean FillOutside (tree_t *tree, int hullnum) { int i; int s; qboolean inside; vec3_t origin; qprintf ("----- FillOutside ----\n"); if (nofill) { printf ("skipped\n"); return false; } inside = false; for (i=1 ; i<num_entities ; i++) { GetVectorForKey (&entities[i], "origin", origin); if (DotProduct (origin, origin) >= 0.1) { if (PlaceOccupant (i, origin, tree->headnode)) inside = true; } } if (!inside) { printf ("Hullnum %i: No entities in empty space -- no filling performed\n", hullnum); return false; } s = !(outside_node.portals->nodes[1] == &outside_node); // first check to see if an occupied leaf is hit outleafs = 0; valid++; prevleaknode = NULL; if (RecursiveFillOutside (outside_node.portals->nodes[s], hullnum, false)) { if (leakfile) fclose(leakfile); leakfile = NULL; if (!hullnum) { GetVectorForKey (&entities[hit_occupied], "origin", origin); qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); qprintf ("reached occupant at: (%4.0f,%4.0f,%4.0f)\n", origin[0], origin[1], origin[2]); qprintf ("no filling performed\n"); qprintf ("leak file written to %s\n", filename_pts); qprintf ("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); } // remove faces from filled in leafs ClearOutFaces (tree->headnode); return false; } // now go back and fill things in valid++; RecursiveFillOutside (outside_node.portals->nodes[s], hullnum, true); // remove faces from filled in leafs ClearOutFaces (tree->headnode); qprintf ("%4i outleafs\n", outleafs); return true; }