Skip to content

Commit

Permalink
qbsp: never merge across liquids, deprecate -nomergeacrossliquids
Browse files Browse the repository at this point in the history
we've had complaints from both Q1 and Q2 users with water caustics
leaking out from underwater. This was an attempt to save a few faces,
seems it's not worth the trouble.
  • Loading branch information
ericwa committed Dec 8, 2024
1 parent dabae01 commit 0f1a718
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 29 deletions.
8 changes: 0 additions & 8 deletions docs/qbsp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,6 @@ Options

Don't perform face merging.

.. option:: -nomergeacrossliquids

Don't merge faces above and below a liquid.

This is for maps targetting ezQuake (Q1) and Paintball2 (Q2) water caustics,
where the effect is applied per-face and breaks if a face is partially above
and partially below water.

.. option:: -noedgereuse

Don't reuse edges (may be useful for debugging software rendering).
Expand Down
2 changes: 1 addition & 1 deletion include/qbsp/qbsp.hh
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public:
setting_int32 subdivide;
setting_bool nofill;
setting_bool nomerge;
setting_bool nomergeacrossliquids;
setting_bool nomergeacrossliquids; // deprecated
setting_bool noedgereuse;
setting_bool noclip;
setting_bool noskip;
Expand Down
12 changes: 5 additions & 7 deletions qbsp/merge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,11 @@ static std::unique_ptr<face_t> TryMerge(const face_t *f1, const face_t *f2)
f1->original_side->lmshift != f2->original_side->lmshift)
return NULL;

if (qbsp_options.nomergeacrossliquids.value()) {
// if requested, block merging across water boundaries;
// ezQuake/nQuake (Q1) and Paintball2 (Q2) water caustics will leak onto
// above-water faces.
if (f1->contents[0].is_liquid(qbsp_options.target_game) != f2->contents[0].is_liquid(qbsp_options.target_game))
return nullptr;
}
// block merging across water boundaries;
// ezQuake/nQuake (Q1) and Paintball2 (Q2) water caustics will leak onto
// above-water faces.
if (f1->contents[0].is_liquid(qbsp_options.target_game) != f2->contents[0].is_liquid(qbsp_options.target_game))
return nullptr;

// Q1: don't merge across sky boundary - we delete faces inside sky
if (f1->contents[0].is_sky(qbsp_options.target_game) != f2->contents[0].is_sky(qbsp_options.target_game))
Expand Down
3 changes: 1 addition & 2 deletions qbsp/qbsp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -465,8 +465,7 @@ qbsp_settings::qbsp_settings()
"change the subdivide threshold, in luxels. 0 will disable subdivision entirely"},
nofill{this, "nofill", false, &debugging_group, "don't perform outside filling"},
nomerge{this, "nomerge", false, &debugging_group, "don't perform face merging"},
nomergeacrossliquids{this, "nomergeacrossliquids", false, &common_format_group,
"block merging faces that cross above and below water"},
nomergeacrossliquids{this, "nomergeacrossliquids", false, &common_format_group, "deprecated, no effect"},
noedgereuse{this, "noedgereuse", false, &debugging_group, "don't reuse edges (for debugging software rendering)"},
noclip{this, "noclip", false, &common_format_group, "don't write clip nodes (Q1-like BSP formats)"},
noskip{this, "noskip", false, &debugging_group, "don't remove faces with the 'skip' texture"},
Expand Down
8 changes: 4 additions & 4 deletions tests/test_qbsp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2401,7 +2401,7 @@ TEST(qbspQ1, tjuncMatrix)
EXPECT_FALSE(has_tjunc(INDEX_SOLID, INDEX_DETAIL_FENCE_MIRRORINSIDE));
EXPECT_FALSE(has_tjunc(INDEX_SOLID, INDEX_DETAIL_ILLUSIONARY));
EXPECT_FALSE(has_tjunc(INDEX_SOLID, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
EXPECT_FALSE(has_tjunc(INDEX_SOLID, INDEX_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SOLID, INDEX_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SOLID, INDEX_SKY));
}

Expand All @@ -2415,7 +2415,7 @@ TEST(qbspQ1, tjuncMatrix)
EXPECT_FALSE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_DETAIL_ILLUSIONARY));
EXPECT_FALSE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
// see INDEX_SOLID, INDEX_WATER explanation
EXPECT_FALSE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_SKY));
}

Expand All @@ -2431,7 +2431,7 @@ TEST(qbspQ1, tjuncMatrix)
EXPECT_FALSE(has_tjunc(INDEX_DETAIL_WALL, INDEX_DETAIL_ILLUSIONARY));
EXPECT_FALSE(has_tjunc(INDEX_DETAIL_WALL, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
// see INDEX_SOLID, INDEX_WATER explanation
EXPECT_FALSE(has_tjunc(INDEX_DETAIL_WALL, INDEX_WATER));
EXPECT_TRUE(has_tjunc(INDEX_DETAIL_WALL, INDEX_WATER));
// sky cuts a hole in detail_wall
EXPECT_TRUE(has_tjunc(INDEX_DETAIL_WALL, INDEX_SKY));
}
Expand Down Expand Up @@ -2535,7 +2535,7 @@ TEST(qbspQ1, tjuncMatrix)
EXPECT_FALSE(has_tjunc(INDEX_SKY, INDEX_DETAIL_FENCE_MIRRORINSIDE));
EXPECT_FALSE(has_tjunc(INDEX_SKY, INDEX_DETAIL_ILLUSIONARY));
EXPECT_FALSE(has_tjunc(INDEX_SKY, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
EXPECT_FALSE(has_tjunc(INDEX_SKY, INDEX_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SKY, INDEX_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SKY, INDEX_SKY));
}
}
Expand Down
15 changes: 8 additions & 7 deletions tests/test_qbsp_q2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -920,8 +920,9 @@ TEST(testmapsQ2, tjuncMatrix)
EXPECT_TRUE(has_tjunc(INDEX_DETAIL_WALL, INDEX_SOLID));
// same as INDEX_DETAIL_WALL, INDEX_SOLID
EXPECT_TRUE(has_tjunc(INDEX_DETAIL_WALL, INDEX_SOLID_DETAIL));
EXPECT_FALSE(has_tjunc(INDEX_DETAIL_WALL, INDEX_TRANSPARENT_WATER));
EXPECT_FALSE(has_tjunc(INDEX_DETAIL_WALL, INDEX_OPAQUE_WATER));
// 2.0.0-alpha9: water welds with everything
EXPECT_TRUE(has_tjunc(INDEX_DETAIL_WALL, INDEX_TRANSPARENT_WATER));
EXPECT_TRUE(has_tjunc(INDEX_DETAIL_WALL, INDEX_OPAQUE_WATER));
EXPECT_FALSE(has_tjunc(INDEX_DETAIL_WALL, INDEX_OPAQUE_MIST));
EXPECT_FALSE(has_tjunc(INDEX_DETAIL_WALL, INDEX_TRANSPARENT_WINDOW));
EXPECT_FALSE(has_tjunc(INDEX_DETAIL_WALL, INDEX_OPAQUE_AUX));
Expand All @@ -934,7 +935,7 @@ TEST(testmapsQ2, tjuncMatrix)
EXPECT_FALSE(has_tjunc(INDEX_SOLID, INDEX_DETAIL_WALL));
EXPECT_TRUE(has_tjunc(INDEX_SOLID, INDEX_SOLID));
EXPECT_TRUE(has_tjunc(INDEX_SOLID, INDEX_SOLID_DETAIL));
EXPECT_FALSE(has_tjunc(INDEX_SOLID, INDEX_TRANSPARENT_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SOLID, INDEX_TRANSPARENT_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SOLID, INDEX_OPAQUE_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SOLID, INDEX_OPAQUE_MIST));
EXPECT_FALSE(has_tjunc(INDEX_SOLID, INDEX_TRANSPARENT_WINDOW));
Expand All @@ -947,7 +948,7 @@ TEST(testmapsQ2, tjuncMatrix)
EXPECT_FALSE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_DETAIL_WALL));
EXPECT_TRUE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_SOLID));
EXPECT_TRUE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_SOLID_DETAIL));
EXPECT_FALSE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_TRANSPARENT_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_TRANSPARENT_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_OPAQUE_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_OPAQUE_MIST));
EXPECT_FALSE(has_tjunc(INDEX_SOLID_DETAIL, INDEX_TRANSPARENT_WINDOW));
Expand Down Expand Up @@ -1013,7 +1014,7 @@ TEST(testmapsQ2, tjuncMatrix)
EXPECT_TRUE(has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_SOLID_DETAIL));
// translucent window and translucent water weld
EXPECT_TRUE(has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_TRANSPARENT_WATER));
EXPECT_FALSE(has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_OPAQUE_WATER));
EXPECT_TRUE(has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_OPAQUE_WATER));
EXPECT_FALSE(has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_OPAQUE_MIST));
EXPECT_TRUE(has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_TRANSPARENT_WINDOW));
// note, aux is lower priority than window, so bottom face of aux gets cut away
Expand All @@ -1028,7 +1029,7 @@ TEST(testmapsQ2, tjuncMatrix)
EXPECT_TRUE(has_tjunc(INDEX_OPAQUE_AUX, INDEX_DETAIL_WALL));
EXPECT_TRUE(has_tjunc(INDEX_OPAQUE_AUX, INDEX_SOLID));
EXPECT_TRUE(has_tjunc(INDEX_OPAQUE_AUX, INDEX_SOLID_DETAIL));
EXPECT_FALSE(has_tjunc(INDEX_OPAQUE_AUX, INDEX_TRANSPARENT_WATER));
EXPECT_TRUE(has_tjunc(INDEX_OPAQUE_AUX, INDEX_TRANSPARENT_WATER));
EXPECT_TRUE(has_tjunc(INDEX_OPAQUE_AUX, INDEX_OPAQUE_WATER));
EXPECT_TRUE(has_tjunc(INDEX_OPAQUE_AUX, INDEX_OPAQUE_MIST));
// window is stronger, cuts a hole which causes aux to weld
Expand All @@ -1042,7 +1043,7 @@ TEST(testmapsQ2, tjuncMatrix)
EXPECT_FALSE(has_tjunc(INDEX_SKY, INDEX_DETAIL_WALL));
EXPECT_TRUE(has_tjunc(INDEX_SKY, INDEX_SOLID));
EXPECT_TRUE(has_tjunc(INDEX_SKY, INDEX_SOLID_DETAIL));
EXPECT_FALSE(has_tjunc(INDEX_SKY, INDEX_TRANSPARENT_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SKY, INDEX_TRANSPARENT_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SKY, INDEX_OPAQUE_WATER));
EXPECT_TRUE(has_tjunc(INDEX_SKY, INDEX_OPAQUE_MIST));
EXPECT_FALSE(has_tjunc(INDEX_SKY, INDEX_TRANSPARENT_WINDOW));
Expand Down

0 comments on commit 0f1a718

Please sign in to comment.