From 6d66e6d5cfd908244ae62f5db0cab94dc11146bf Mon Sep 17 00:00:00 2001 From: Jonathan Date: Fri, 12 Aug 2022 21:38:41 -0400 Subject: [PATCH] group together # of clipped faces, to reduce console spam of Q1 maps always allow midplane split for hulls --- include/qbsp/brush.hh | 2 +- include/qbsp/map.hh | 2 +- qbsp/brush.cc | 40 +++++++++++++++++++++++----------------- qbsp/map.cc | 2 +- qbsp/qbsp.cc | 9 +++++++-- tests/test_qbsp.cc | 2 +- 6 files changed, 34 insertions(+), 23 deletions(-) diff --git a/include/qbsp/brush.hh b/include/qbsp/brush.hh index 760696a2..7ea6dcdd 100644 --- a/include/qbsp/brush.hh +++ b/include/qbsp/brush.hh @@ -93,5 +93,5 @@ struct bspbrush_t bspbrush_t clone() const; }; -std::optional LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush, const contentflags_t &contents, const int hullnum); +std::optional LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush, const contentflags_t &contents, const int hullnum, std::optional> num_clipped); bool CreateBrushWindings(bspbrush_t *brush); \ No newline at end of file diff --git a/include/qbsp/map.hh b/include/qbsp/map.hh index c4494f00..f3a22917 100644 --- a/include/qbsp/map.hh +++ b/include/qbsp/map.hh @@ -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 CSGFace( face_t *srcface, const mapentity_t *srcentity, const bspbrush_t *srcbrush, const node_t *srcnode); diff --git a/qbsp/brush.cc b/qbsp/brush.cc index 32a5317c..f986e7fb 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -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> 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 LoadBrush(const mapentity_t *src, mapbrush_t *mapbrush, const contentflags_t &contents, - const int hullnum) + const int hullnum, std::optional> num_clipped) { // create the brush bspbrush_t brush{}; @@ -352,7 +358,7 @@ std::optional 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 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); } } } diff --git a/qbsp/map.cc b/qbsp/map.cc index 8fe2c19f..ffd6b261 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -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))); diff --git a/qbsp/qbsp.cc b/qbsp/qbsp.cc index f0460a83..c127604c 100644 --- a/qbsp/qbsp.cc +++ b/qbsp/qbsp.cc @@ -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()); diff --git a/tests/test_qbsp.cc b/tests/test_qbsp.cc index 9a264850..34723723 100644 --- a/tests/test_qbsp.cc +++ b/tests/test_qbsp.cc @@ -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()); }