qbsp: fix void faces in qbsp_simple_sealed2.map

This commit is contained in:
Eric Wasylishen 2022-04-16 02:09:11 -06:00
parent f467257f72
commit d2ae49c976
2 changed files with 73 additions and 2 deletions

View File

@ -523,6 +523,66 @@ void MakeMarkFaces(mapentity_t* entity, node_t* node)
MakeMarkFaces(entity, node->children[1]);
}
static std::list<face_t *> ClipFacesToTree_r(node_t *node, std::list<face_t *> faces)
{
if (node->planenum == PLANENUM_LEAF) {
if (node->contents.is_solid(options.target_game)) {
// solids eat any faces that reached this point
return {};
}
// other content types let the faces thorugh
// fixme-brushbsp: detail?
return faces;
}
const qbsp_plane_t &splitplane = map.planes[node->planenum];
std::list<face_t *> front, back;
for (auto *face : faces) {
auto [frontFragment, backFragment] = SplitFace(face, splitplane);
if (frontFragment) {
front.push_back(frontFragment);
}
if (backFragment) {
back.push_back(backFragment);
}
}
front = ClipFacesToTree_r(node->children[0], front);
back = ClipFacesToTree_r(node->children[1], back);
// merge lists
front.splice(front.end(), back);
return front;
}
static std::list<face_t*> ClipFacesToTree(node_t* node, std::list<face_t*> faces)
{
// handles the first level - faces are all supposed to be lying exactly on `node`
for (auto *face : faces) {
Q_assert(face->planenum == node->planenum);
}
std::list<face_t *> front, back;
for (auto *face : faces) {
if (face->planeside == 0) {
front.push_back(face);
} else {
back.push_back(face);
}
}
front = ClipFacesToTree_r(node->children[0], front);
back = ClipFacesToTree_r(node->children[1], back);
// merge lists
front.splice(front.end(), back);
return front;
}
static void AddFaceToTree_r(mapentity_t* entity, face_t *face, brush_t *srcbrush, node_t* node)
{
if (node->planenum == PLANENUM_LEAF) {
@ -537,9 +597,13 @@ static void AddFaceToTree_r(mapentity_t* entity, face_t *face, brush_t *srcbrush
++c_nodefaces;
// csg it
auto csgfaces = CSGFace(face, entity, srcbrush, node);
std::list<face_t *> faces = CSGFace(face, entity, srcbrush, node);
for (face_t *csgface : csgfaces) {
// clip them to the descendant parts of the BSP
// (otherwise we could have faces floating in the void on this node)
faces = ClipFacesToTree(node, faces);
for (face_t *csgface : faces) {
// subdivide large faces
// fixme-brushbsp: weird calling convention
auto parts = std::list<face_t *>{csgface};

View File

@ -40,6 +40,9 @@ static mbsp_t LoadTestmap(const std::filesystem::path &name)
{
map.reset();
options.nopercent.setValue(true);
options.noprogress.setValue(true);
options.szMapName = std::filesystem::path(testmaps_dir) / name;
options.szBSPName = options.szMapName;
options.szBSPName.replace_extension(".bsp");
@ -265,4 +268,8 @@ TEST(qsbsp, simple_sealed2)
ASSERT_EQ(result.dleafs[0].contents, CONTENTS_SOLID);
ASSERT_EQ(result.dleafs[1].contents, CONTENTS_EMPTY);
ASSERT_EQ(result.dleafs[2].contents, CONTENTS_EMPTY);
// L-shaped room
// 2 ceiling + 2 floor + 6 wall faces
ASSERT_EQ(result.dfaces.size(), 10);
}