qbsp: fix handling of duplicate planes

fixes spurious leak in e1m4.map
This commit is contained in:
Eric Wasylishen 2017-07-15 13:51:26 -06:00
parent a3cb25b46a
commit 8b9f5ea40a
4 changed files with 56 additions and 2 deletions

View File

@ -37,6 +37,7 @@ class mapbrush_t;
int Brush_ListCountWithCFlags(const brush_t *brush, int cflags); int Brush_ListCountWithCFlags(const brush_t *brush, int cflags);
int Brush_ListCount(const brush_t *brush); 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); brush_t *LoadBrush(const mapbrush_t *mapbrush, const vec3_t rotate_offset, const int hullnum);
void FreeBrushes(brush_t *brushlist); void FreeBrushes(brush_t *brushlist);

View File

@ -929,6 +929,19 @@ Brush_ListCount(const brush_t *brush)
return Brush_ListCountWithCFlags(brush, 0); 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 void
Entity_SortBrushes(mapentity_t *dst) Entity_SortBrushes(mapentity_t *dst)
{ {

View File

@ -1476,10 +1476,12 @@ ParseBrush(parser_t *parser, const mapentity_t *entity)
continue; continue;
/* Check for duplicate planes */ /* Check for duplicate planes */
bool discardFace = false;
for (int i = 0; i<brush.numfaces; i++) { for (int i = 0; i<brush.numfaces; i++) {
const mapface_t &check = brush.face(i); const mapface_t &check = brush.face(i);
if (PlaneEqual(&check.plane, &face->plane)) { if (PlaneEqual(&check.plane, &face->plane)) {
Message(msgWarning, warnBrushDuplicatePlane, parser->linenum); Message(msgWarning, warnBrushDuplicatePlane, parser->linenum);
discardFace = true;
continue; continue;
} }
if (PlaneInvEqual(&check.plane, &face->plane)) { if (PlaneInvEqual(&check.plane, &face->plane)) {
@ -1488,6 +1490,8 @@ ParseBrush(parser_t *parser, const mapentity_t *entity)
continue; continue;
} }
} }
if (discardFace)
continue;
/* Save the face, update progress */ /* Save the face, update progress */

View File

@ -23,8 +23,8 @@ static const mapface_t *Mapbrush_FirstFaceWithTextureName(const mapbrush_t *brus
return nullptr; return nullptr;
} }
static std::array<qvec4f, 2> static mapentity_t
GetTexvecs(const char *map, const char *texname) LoadMap(const char *map)
{ {
parser_t parser; parser_t parser;
ParserInit(&parser, map); ParserInit(&parser, map);
@ -33,6 +33,14 @@ GetTexvecs(const char *map, const char *texname)
// FIXME: adds the brush to the global map... // FIXME: adds the brush to the global map...
Q_assert(ParseEntity(&parser, &worldspawn)); Q_assert(ParseEntity(&parser, &worldspawn));
return worldspawn;
}
static std::array<qvec4f, 2>
GetTexvecs(const char *map, const char *texname)
{
mapentity_t worldspawn = LoadMap(map);
const mapbrush_t *mapbrush = &worldspawn.mapbrush(0); const mapbrush_t *mapbrush = &worldspawn.mapbrush(0);
const mapface_t *mapface = Mapbrush_FirstFaceWithTextureName(mapbrush, "tech02_1"); const mapface_t *mapface = Mapbrush_FirstFaceWithTextureName(mapbrush, "tech02_1");
Q_assert(nullptr != mapface); Q_assert(nullptr != mapface);
@ -84,3 +92,31 @@ TEST(qbsp, testTextureIssue) {
} }
#endif #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);
}