From 8b9f5ea40a92d340fad2f4dd8c409ac0cee074e3 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sat, 15 Jul 2017 13:51:26 -0600 Subject: [PATCH] qbsp: fix handling of duplicate planes fixes spurious leak in e1m4.map --- include/qbsp/brush.hh | 1 + qbsp/brush.cc | 13 +++++++++++++ qbsp/map.cc | 4 ++++ qbsp/test_qbsp.cc | 40 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/include/qbsp/brush.hh b/include/qbsp/brush.hh index 17bd8b3b..1962ace4 100644 --- a/include/qbsp/brush.hh +++ b/include/qbsp/brush.hh @@ -37,6 +37,7 @@ class mapbrush_t; int Brush_ListCountWithCFlags(const brush_t *brush, int cflags); int Brush_ListCount(const brush_t *brush); +int Brush_NumFaces(const brush_t *brush); brush_t *LoadBrush(const mapbrush_t *mapbrush, const vec3_t rotate_offset, const int hullnum); void FreeBrushes(brush_t *brushlist); diff --git a/qbsp/brush.cc b/qbsp/brush.cc index b9da1a55..844bc38f 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -929,6 +929,19 @@ Brush_ListCount(const brush_t *brush) return Brush_ListCountWithCFlags(brush, 0); } +static int FaceListCount(const face_t *facelist) +{ + if (facelist) + return 1 + FaceListCount(facelist->next); + else + return 0; +} + +int Brush_NumFaces(const brush_t *brush) +{ + return FaceListCount(brush->faces); +} + void Entity_SortBrushes(mapentity_t *dst) { diff --git a/qbsp/map.cc b/qbsp/map.cc index 19487145..6f243eca 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -1476,10 +1476,12 @@ ParseBrush(parser_t *parser, const mapentity_t *entity) continue; /* Check for duplicate planes */ + bool discardFace = false; for (int i = 0; iplane)) { Message(msgWarning, warnBrushDuplicatePlane, parser->linenum); + discardFace = true; continue; } if (PlaneInvEqual(&check.plane, &face->plane)) { @@ -1488,6 +1490,8 @@ ParseBrush(parser_t *parser, const mapentity_t *entity) continue; } } + if (discardFace) + continue; /* Save the face, update progress */ diff --git a/qbsp/test_qbsp.cc b/qbsp/test_qbsp.cc index 36a84de7..730107f2 100644 --- a/qbsp/test_qbsp.cc +++ b/qbsp/test_qbsp.cc @@ -23,8 +23,8 @@ static const mapface_t *Mapbrush_FirstFaceWithTextureName(const mapbrush_t *brus return nullptr; } -static std::array -GetTexvecs(const char *map, const char *texname) +static mapentity_t +LoadMap(const char *map) { parser_t parser; ParserInit(&parser, map); @@ -33,6 +33,14 @@ GetTexvecs(const char *map, const char *texname) // FIXME: adds the brush to the global map... Q_assert(ParseEntity(&parser, &worldspawn)); + return worldspawn; +} + +static std::array +GetTexvecs(const char *map, const char *texname) +{ + mapentity_t worldspawn = LoadMap(map); + const mapbrush_t *mapbrush = &worldspawn.mapbrush(0); const mapface_t *mapface = Mapbrush_FirstFaceWithTextureName(mapbrush, "tech02_1"); Q_assert(nullptr != mapface); @@ -84,3 +92,31 @@ TEST(qbsp, testTextureIssue) { } #endif } + +TEST(qbsp, duplicatePlanes) { + // a brush from e1m4.map with 7 planes, only 6 unique. + const char *mapWithDuplicatePlanes = R"( + { + "classname" "worldspawn" + { + ( 512 120 1184 ) ( 512 104 1184 ) ( 512 8 1088 ) WBRICK1_5 0 0 0 1.000000 1.000000 + ( 1072 104 1184 ) ( 176 104 1184 ) ( 176 8 1088 ) WBRICK1_5 0 0 0 1.000000 1.000000 + ( 896 56 1184 ) ( 896 72 1184 ) ( 896 -24 1088 ) WBRICK1_5 0 0 0 1.000000 1.000000 + ( 176 88 1184 ) ( 1072 88 1184 ) ( 1072 -8 1088 ) WBRICK1_5 0 0 0 1.000000 1.000000 + ( 176 88 1184 ) ( 176 104 1184 ) ( 1072 104 1184 ) WBRICK1_5 0 0 0 1.000000 1.000000 + ( 1072 8 1088 ) ( 176 8 1088 ) ( 176 -8 1088 ) WBRICK1_5 0 0 0 1.000000 1.000000 + ( 960 8 1088 ) ( 864 104 1184 ) ( 848 104 1184 ) WBRICK1_5 0 0 0 1.000000 1.000000 + } + } + )"; + + mapentity_t worldspawn = LoadMap(mapWithDuplicatePlanes); + ASSERT_EQ(1, worldspawn.nummapbrushes); + EXPECT_EQ(0, worldspawn.numbrushes); + EXPECT_EQ(6, worldspawn.mapbrush(0).numfaces); + + brush_t *brush = LoadBrush(&worldspawn.mapbrush(0), vec3_origin, 0); + ASSERT_NE(nullptr, brush); + EXPECT_EQ(6, Brush_NumFaces(brush)); + FreeMem(brush, BRUSH, 1); +}