qbsp: add very rough pass of building visible faces

- faces are subdivided where neeed
- markfaces not calculated accurately
- overlaps/clipping not handled
This commit is contained in:
Eric Wasylishen 2022-02-13 19:51:59 -07:00
parent 1fbfd199c5
commit 055f865ef0
5 changed files with 102 additions and 43 deletions

View File

@ -25,3 +25,4 @@
std::vector<surface_t> GatherNodeFaces(node_t *headnode);
void FreeNodes(node_t* node);
void MakeVisibleFaces(mapentity_t *entity, node_t *headnode);

View File

@ -605,11 +605,15 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum)
else
nodes = SolidBSP(entity, entity == pWorldEnt());
MakeVisibleFaces(entity, nodes);
// build all the portals in the bsp tree
// some portals are solid polygons, and some are paths to other leafs
if (entity == pWorldEnt()) {
// assume non-world bmodels are simple
PortalizeWorld(entity, nodes, hullnum);
#if 0
if (!options.fNofill && FillOutside(nodes, hullnum)) {
FreeAllPortals(nodes);
@ -632,6 +636,7 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum)
TJunc(entity, nodes);
}
}
#endif
// Area portals
if (options.target_game->id == GAME_QUAKE_II) {

View File

@ -819,47 +819,6 @@ static void CreateLeaf(const std::vector<brush_t> &brushes, node_t *leafnode)
#endif
}
// fixme-brushbsp: move SubdivideFace call somewhere else
#if 0
/*
==================
LinkNodeFaces
First subdivides surface->faces.
Then, duplicates the list of subdivided faces and returns it.
For each surface->faces, ->original is set to the respective duplicate that
is returned here (why?).
Called in parallel.
==================
*/
static std::list<face_t *> LinkNodeFaces(surface_t &surface)
{
// subdivide large faces
for (auto it = surface.faces.begin(); it != surface.faces.end(); it++) {
it = SubdivideFace(it, surface.faces);
}
surface.faces.reverse();
nodefaces += surface.faces.size();
std::list<face_t *> list;
// copy
for (auto &f : surface.faces) {
face_t *newf = new face_t(*f);
Q_assert(newf->original == nullptr);
list.push_front(newf);
f->original = newf;
}
return list;
}
#endif
/*
==================
PartitionBrushes

View File

@ -511,3 +511,97 @@ int MakeFaceEdges(mapentity_t *entity, node_t *headnode)
return firstface;
}
//===========================================================================
static int c_nodefaces;
static void AddMarksurfaces_r(face_t *face, node_t *node)
{
if (node->planenum == PLANENUM_LEAF) {
node->markfaces.push_back(face);
return;
}
AddMarksurfaces_r(face, node->children[0]);
AddMarksurfaces_r(face, node->children[1]);
}
void AddFaceToTree_r(face_t *face, node_t* node)
{
if (node->planenum == PLANENUM_LEAF) {
if (!face->w.size()) {
// spurious
return;
}
FError("couldn't find node for face");
}
if (face->planenum == node->planenum) {
// found the correct plane - add the face to it.
++c_nodefaces;
// subdivide large faces
// fixme-brushbsp: weird calling convention
auto parts = std::list<face_t *>{face};
for (auto it = parts.begin(); it != parts.end(); it++) {
it = SubdivideFace(it, parts);
}
for (face_t *part : parts) {
node->facelist.push_back(part);
// Now that the final face has been added
// fixme-brushbsp: do this as a postprocessing step
AddMarksurfaces_r(part, node);
}
return;
}
// fixme-brushbsp: we need to handle the case of the face being near enough that it gets clipped away,
// but not face->planenum == node->planenum
auto [frontWinding, backWinding] = face->w.clip(map.planes[node->planenum]);
if (frontWinding) {
auto *newFace = new face_t{*face};
newFace->w = *frontWinding;
AddFaceToTree_r(newFace, node->children[0]);
}
if (backWinding) {
auto *newFace = new face_t{*face};
newFace->w = *backWinding;
AddFaceToTree_r(newFace, node->children[1]);
}
delete face;
}
/*
================
MakeVisibleFaces
Given a completed BSP tree and a list of brushes (in `entity`),
- filters the brush faces into the BSP, finding the correct nodes they end up on
- clips the faces by other brushes.
first iteration, we can just do an exhaustive check against all brushes
================
*/
void MakeVisibleFaces(mapentity_t* entity, node_t* headnode)
{
c_nodefaces = 0;
for (auto &brush : entity->brushes) {
for (auto &face : brush.faces) {
face_t *temp = NewFaceFromFace(&face);
temp->w = face.w;
AddFaceToTree_r(temp, headnode);
}
}
LogPrint("{} nodefaces\n", c_nodefaces);
}

View File

@ -13,8 +13,8 @@
( -80 -96 80 ) ( -81 -96 80 ) ( -80 -96 81 ) orangestuff8 [ -1 0 0 16 ] [ 0 0 -1 0 ] 180 1 1
( -80 -432 80 ) ( -80 -431 80 ) ( -81 -432 80 ) orangestuff8 [ 1 0 0 -16 ] [ 0 -1 0 16 ] 180 1 1
( -160 -112 96 ) ( -161 -112 96 ) ( -160 -111 96 ) orangestuff8 [ -1 0 0 16 ] [ 0 -1 0 16 ] 180 1 1
( -160 -32 96 ) ( -160 -32 97 ) ( -161 -32 96 ) orangestuff8 [ 1 0 0 -16 ] [ 0 0 -1 0 ] 180 1 1
( -64 -432 80 ) ( -64 -432 81 ) ( -64 -431 80 ) orangestuff8 [ 0 -1 0 16 ] [ 0 0 -1 0 ] 0 1 1
( -160 128 96 ) ( -160 128 97 ) ( -161 128 96 ) orangestuff8 [ 1 0 0 -16 ] [ 0 0 -1 0 ] 180 1 1
( 144 -432 80 ) ( 144 -432 81 ) ( 144 -431 80 ) orangestuff8 [ 0 -1 0 16 ] [ 0 0 -1 0 ] 0 1 1
}
// brush 1
{