group together # of clipped faces, to reduce console spam of Q1 maps

always allow midplane split for hulls
This commit is contained in:
Jonathan 2022-08-12 21:38:41 -04:00
parent e7647f5ca7
commit 6d66e6d5cf
6 changed files with 34 additions and 23 deletions

View File

@ -93,5 +93,5 @@ struct bspbrush_t
bspbrush_t clone() const;
};
std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush, const contentflags_t &contents, const int hullnum);
std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush, const contentflags_t &contents, const int hullnum, std::optional<std::reference_wrapper<size_t>> num_clipped);
bool CreateBrushWindings(bspbrush_t *brush);

View File

@ -345,7 +345,7 @@ qvec3d FixRotateOrigin(mapentity_t *entity);
constexpr int HULL_COLLISION = -1;
/* Create BSP brushes from map brushes */
void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_t::container &brushes);
void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_t::container &brushes, size_t &num_clipped);
std::list<face_t *> CSGFace(
face_t *srcface, const mapentity_t *srcentity, const bspbrush_t *srcbrush, const node_t *srcnode);

View File

@ -103,16 +103,22 @@ CheckFace
Note: this will not catch 0 area polygons
=================
*/
static void CheckFace(side_t *face, const mapface_t &sourceface)
static void CheckFace(side_t *face, const mapface_t &sourceface, std::optional<std::reference_wrapper<size_t>> num_clipped)
{
if (face->w.size() < 3) {
if (face->w.size() == 2) {
logging::print(
"WARNING: {}: partially clipped into degenerate polygon @ ({}) - ({})\n", sourceface.line, face->w[0], face->w[1]);
} else if (face->w.size() == 1) {
logging::print("WARNING: {}: partially clipped into degenerate polygon @ ({})\n", sourceface.line, face->w[0]);
} else {
logging::print("WARNING: {}: completely clipped away\n", sourceface.line);
if (qbsp_options.verbose.value()) {
if (face->w.size() == 2) {
logging::print(
"WARNING: {}: partially clipped into degenerate polygon @ ({}) - ({})\n", sourceface.line, face->w[0], face->w[1]);
} else if (face->w.size() == 1) {
logging::print("WARNING: {}: partially clipped into degenerate polygon @ ({})\n", sourceface.line, face->w[0]);
} else {
logging::print("WARNING: {}: completely clipped away\n", sourceface.line);
}
}
if (num_clipped) {
(*num_clipped)++;
}
face->w.clear();
@ -151,7 +157,7 @@ static void CheckFace(side_t *face, const mapface_t &sourceface)
for (size_t j = i + 1; j < face->w.size(); j++)
face->w[j - 1] = face->w[j];
face->w.resize(face->w.size() - 1);
CheckFace(face, sourceface);
CheckFace(face, sourceface, num_clipped);
break;
}
@ -298,7 +304,7 @@ Converts a mapbrush to a bsp brush
===============
*/
std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush, const contentflags_t &contents,
const int hullnum)
const int hullnum, std::optional<std::reference_wrapper<size_t>> num_clipped)
{
// create the brush
bspbrush_t brush{};
@ -352,7 +358,7 @@ std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush
}
for (auto &face : brush.sides) {
CheckFace(&face, *face.source);
CheckFace(&face, *face.source, num_clipped);
}
// Rotatable objects must have a bounding box big enough to
@ -393,7 +399,7 @@ std::optional<bspbrush_t> LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush
//=============================================================================
static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hullnum, content_stats_base_t &stats, bspbrush_t::container &brushes, logging::percent_clock &clock)
static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hullnum, content_stats_base_t &stats, bspbrush_t::container &brushes, logging::percent_clock &clock, size_t &num_clipped)
{
// _omitbrushes 1 just discards all brushes in the entity.
// could be useful for geometry guides, selective compilation, etc.
@ -494,7 +500,7 @@ static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hulln
*/
if (hullnum != HULL_COLLISION && contents.is_clip(qbsp_options.target_game)) {
if (hullnum == 0) {
if (auto brush = LoadBrush(src, &mapbrush, contents, hullnum)) {
if (auto brush = LoadBrush(src, &mapbrush, contents, hullnum, num_clipped)) {
dst->bounds += brush->bounds;
}
continue;
@ -541,7 +547,7 @@ static void Brush_LoadEntity(mapentity_t *dst, mapentity_t *src, const int hulln
contents.set_clips_same_type(clipsametype);
contents.illusionary_visblocker = func_illusionary_visblocker;
auto brush = LoadBrush(src, &mapbrush, contents, hullnum);
auto brush = LoadBrush(src, &mapbrush, contents, hullnum, num_clipped);
if (!brush) {
continue;
@ -562,7 +568,7 @@ hullnum HULL_COLLISION should contain ALL brushes. (used by BSPX_CreateBrushList
hullnum 0 does not contain clip brushes.
============
*/
void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_t::container &brushes)
void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_t::container &brushes, size_t &num_clipped)
{
logging::funcheader();
@ -570,7 +576,7 @@ void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_t::contai
logging::percent_clock clock(0);
clock.displayElapsed = (entity == map.world_entity());
Brush_LoadEntity(entity, entity, hullnum, *stats, brushes, clock);
Brush_LoadEntity(entity, entity, hullnum, *stats, brushes, clock, num_clipped);
/*
* If this is the world entity, find all func_group and func_detail
@ -590,7 +596,7 @@ void Brush_LoadEntity(mapentity_t *entity, const int hullnum, bspbrush_t::contai
ProcessAreaPortal(source);
if (IsWorldBrushEntity(source) || IsNonRemoveWorldBrushEntity(source)) {
Brush_LoadEntity(entity, source, hullnum, *stats, brushes, clock);
Brush_LoadEntity(entity, source, hullnum, *stats, brushes, clock, num_clipped);
}
}
}

View File

@ -2860,7 +2860,7 @@ static void TestExpandBrushes(mapentity_t *src)
for (auto &mapbrush : src->mapbrushes) {
auto hull1brush = LoadBrush(src, &mapbrush, {CONTENTS_SOLID},
qbsp_options.target_game->id == GAME_QUAKE_II ? HULL_COLLISION : 1);
qbsp_options.target_game->id == GAME_QUAKE_II ? HULL_COLLISION : 1, std::nullopt);
if (hull1brush) {
hull1brushes.emplace_back(bspbrush_t::make_ptr(std::move(*hull1brush)));

View File

@ -451,7 +451,12 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum)
/*
* Convert the map brushes (planes) into BSP brushes (polygons)
*/
Brush_LoadEntity(entity, hullnum, brushes);
size_t num_clipped = 0;
Brush_LoadEntity(entity, hullnum, brushes, num_clipped);
if (num_clipped && !qbsp_options.verbose.value()) {
logging::print("WARNING: {} faces were clipped away. This is normal for expanded hulls; use -verbose if you need more info.\n", num_clipped);
}
size_t num_sides = 0;
for (size_t i = 0; i < brushes.size(); ++i) {
@ -481,7 +486,7 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum)
if (FillOutside(entity, tree.get(), hullnum, brushes)) {
// make a really good tree
tree.reset();
tree = BrushBSP(entity, brushes, false);
tree = BrushBSP(entity, brushes, std::nullopt);
// fill again so PruneNodes works
MakeTreePortals(tree.get());

View File

@ -398,7 +398,7 @@ TEST_CASE("duplicatePlanes", "[qbsp]")
REQUIRE(1 == worldspawn.mapbrushes.size());
CHECK(6 == worldspawn.mapbrushes.front().faces.size());
auto brush = LoadBrush(&worldspawn, &worldspawn.mapbrushes.front(), {CONTENTS_SOLID}, 0);
auto brush = LoadBrush(&worldspawn, &worldspawn.mapbrushes.front(), {CONTENTS_SOLID}, 0, std::nullopt);
CHECK(6 == brush->sides.size());
}