qbsp: wip import MarkVisibleSides from qbsp3
This commit is contained in:
parent
59d6169b3d
commit
4f3ca8c252
|
|
@ -358,6 +358,28 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
contentflags_t visible_contents(const contentflags_t &a, const contentflags_t &b) const override
|
||||
{
|
||||
if (a.equals(this, b)) {
|
||||
return create_empty_contents();
|
||||
}
|
||||
|
||||
int32_t a_pri = contents_priority(a);
|
||||
int32_t b_pri = contents_priority(b);
|
||||
|
||||
if (a_pri > b_pri) {
|
||||
return a;
|
||||
} else {
|
||||
return b;
|
||||
}
|
||||
// fixme-brushbsp: support detail-illusionary intersecting liquids
|
||||
}
|
||||
|
||||
bool contents_contains(const contentflags_t &a, const contentflags_t &b) const override
|
||||
{
|
||||
return a.equals(this, b);
|
||||
}
|
||||
|
||||
std::string get_contents_display(const contentflags_t &contents) const override
|
||||
{
|
||||
std::string base;
|
||||
|
|
@ -850,6 +872,9 @@ struct gamedef_q2_t : public gamedef_t
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the single content bit of the strongest visible content present
|
||||
*/
|
||||
constexpr int32_t visible_contents(const int32_t &contents) const
|
||||
{
|
||||
for (int32_t i = 1; i <= Q2_LAST_VISIBLE_CONTENTS; i <<= 1) {
|
||||
|
|
@ -907,6 +932,18 @@ struct gamedef_q2_t : public gamedef_t
|
|||
return {a.native | b.native};
|
||||
}
|
||||
|
||||
contentflags_t visible_contents(const contentflags_t &a, const contentflags_t &b) const override
|
||||
{
|
||||
int viscontents = visible_contents(a.native ^ b.native);
|
||||
|
||||
return {viscontents};
|
||||
}
|
||||
|
||||
bool contents_contains(const contentflags_t &a, const contentflags_t &b) const override
|
||||
{
|
||||
return (a.native & b.native) != 0;
|
||||
}
|
||||
|
||||
std::string get_contents_display(const contentflags_t &contents) const override
|
||||
{
|
||||
if (!contents.native) {
|
||||
|
|
|
|||
|
|
@ -292,6 +292,8 @@ struct gamedef_t
|
|||
virtual bool contents_seals_map(const contentflags_t &contents) const = 0;
|
||||
virtual contentflags_t contents_remap_for_export(const contentflags_t &contents) const = 0;
|
||||
virtual contentflags_t combine_contents(const contentflags_t &a, const contentflags_t &b) const = 0;
|
||||
virtual contentflags_t visible_contents(const contentflags_t &a, const contentflags_t &b) const = 0;
|
||||
virtual bool contents_contains(const contentflags_t &a, const contentflags_t &b) const = 0;
|
||||
virtual std::string get_contents_display(const contentflags_t &contents) const = 0;
|
||||
virtual void contents_make_valid(contentflags_t &contents) const = 0;
|
||||
virtual const std::initializer_list<aabb3d> &get_hull_sizes() const = 0;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ struct portal_t
|
|||
portal_t *next[2]; // [0] = next portal in nodes[0]'s list of portals
|
||||
std::optional<winding_t> winding;
|
||||
|
||||
bool sidefound; // false if ->side hasn't been checked
|
||||
face_t *side; // NULL = non-visible // fixme-brushbsp: change to side_t
|
||||
face_t *face[2]; // output face in bsp file
|
||||
};
|
||||
|
|
@ -56,3 +57,4 @@ void MakeTreePortals(tree_t *tree);
|
|||
void FreeTreePortals_r(node_t *node);
|
||||
void AssertNoPortals(node_t *node);
|
||||
void MakeHeadnodePortals(tree_t *tree);
|
||||
void MarkVisibleSides(tree_t *tree, mapentity_t* entity);
|
||||
|
|
|
|||
116
qbsp/portals.cc
116
qbsp/portals.cc
|
|
@ -426,3 +426,119 @@ void FreeTreePortals_r(node_t *node)
|
|||
}
|
||||
node->portals = nullptr;
|
||||
}
|
||||
|
||||
//==============================================================
|
||||
|
||||
/*
|
||||
============
|
||||
FindPortalSide
|
||||
|
||||
Finds a brush side to use for texturing the given portal
|
||||
============
|
||||
*/
|
||||
static void FindPortalSide(portal_t *p)
|
||||
{
|
||||
// decide which content change is strongest
|
||||
// solid > lava > water, etc
|
||||
contentflags_t viscontents = options.target_game->visible_contents(p->nodes[0]->contents, p->nodes[1]->contents);
|
||||
if (viscontents.is_empty(options.target_game))
|
||||
return;
|
||||
|
||||
int planenum = p->onnode->planenum;
|
||||
face_t *bestside = nullptr;
|
||||
float bestdot = 0;
|
||||
|
||||
for (int j = 0; j < 2; j++)
|
||||
{
|
||||
node_t *n = p->nodes[j];
|
||||
auto p1 = map.planes.at(p->onnode->planenum);
|
||||
|
||||
for (brush_t *brush : n->original_brushes)
|
||||
{
|
||||
if (!options.target_game->contents_contains(brush->contents, viscontents))
|
||||
continue;
|
||||
for (face_t &side : brush->faces)
|
||||
{
|
||||
// fixme-brushbsp: port these
|
||||
// if (side.bevel)
|
||||
// continue;
|
||||
// if (side.texinfo == TEXINFO_NODE)
|
||||
// continue; // non-visible
|
||||
if (side.planenum == planenum)
|
||||
{ // exact match
|
||||
bestside = &side;
|
||||
goto gotit;
|
||||
}
|
||||
// see how close the match is
|
||||
auto p2 = map.planes.at(side.planenum);
|
||||
float dot = qv::dot(p1.normal, p2.normal);
|
||||
if (dot > bestdot)
|
||||
{
|
||||
bestdot = dot;
|
||||
bestside = &side;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gotit:
|
||||
if (!bestside)
|
||||
logging::print("WARNING: side not found for portal\n");
|
||||
|
||||
p->sidefound = true;
|
||||
p->side = bestside;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
MarkVisibleSides_r
|
||||
|
||||
===============
|
||||
*/
|
||||
static void MarkVisibleSides_r(node_t *node)
|
||||
{
|
||||
if (node->planenum != PLANENUM_LEAF)
|
||||
{
|
||||
MarkVisibleSides_r(node->children[0]);
|
||||
MarkVisibleSides_r(node->children[1]);
|
||||
return;
|
||||
}
|
||||
|
||||
// empty leafs are never boundary leafs
|
||||
if (node->contents.is_empty(options.target_game))
|
||||
return;
|
||||
|
||||
// see if there is a visible face
|
||||
int s;
|
||||
for (portal_t *p=node->portals ; p ; p = p->next[!s])
|
||||
{
|
||||
s = (p->nodes[0] == node);
|
||||
if (!p->onnode)
|
||||
continue; // edge of world
|
||||
if (!p->sidefound)
|
||||
FindPortalSide(p);
|
||||
if (p->side)
|
||||
p->side->visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
=============
|
||||
MarkVisibleSides
|
||||
|
||||
=============
|
||||
*/
|
||||
void MarkVisibleSides(tree_t *tree, mapentity_t* entity)
|
||||
{
|
||||
logging::print("--- {} ---\n", __func__);
|
||||
|
||||
// clear all the visible flags
|
||||
for (auto &brush : entity->brushes) {
|
||||
for (auto &face : brush->faces) {
|
||||
face.visible = false;
|
||||
}
|
||||
}
|
||||
|
||||
// set visible flags on the sides that are used by portals
|
||||
MarkVisibleSides_r (tree->headnode);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -902,7 +902,8 @@ static void ProcessEntity(mapentity_t *entity, const int hullnum)
|
|||
|
||||
MakeTreePortals(tree);
|
||||
|
||||
MakeVisibleFaces(entity, tree->headnode);
|
||||
MarkVisibleSides(tree, entity);
|
||||
MakeFaces(tree->headnode);
|
||||
|
||||
if (hullnum <= 0 && entity == map.world_entity() && !map.leakfile) {
|
||||
WritePortalFile(tree);
|
||||
|
|
|
|||
|
|
@ -750,10 +750,12 @@ static face_t *FaceFromPortal(portal_t *p, int pside)
|
|||
f->planenum = side->planenum;
|
||||
f->planeside = static_cast<side_t>(pside);
|
||||
f->portal = p;
|
||||
f->lmshift = side->lmshift;
|
||||
|
||||
// don't show insides of windows
|
||||
if (!side->contents[1].is_mirrored(options.target_game))
|
||||
return nullptr;
|
||||
// fixme-brushbsp: restore this?
|
||||
// if (!side->contents[1].is_mirrored(options.target_game))
|
||||
// return nullptr;
|
||||
|
||||
if (pside)
|
||||
{
|
||||
|
|
@ -766,6 +768,9 @@ static face_t *FaceFromPortal(portal_t *p, int pside)
|
|||
f->w = *p->winding;
|
||||
f->contents[1] = p->nodes[0]->contents;
|
||||
}
|
||||
|
||||
UpdateFaceSphere(f);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
|
|
@ -812,7 +817,7 @@ static void MakeFaces_r(node_t *node, makefaces_stats_t& stats)
|
|||
face_t *f = FaceFromPortal(p, s);
|
||||
if (f)
|
||||
{
|
||||
c_nodefaces++;
|
||||
stats.c_nodefaces++;
|
||||
p->face[s] = f;
|
||||
p->onnode->facelist.push_back(f);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue