qbsp: adjust tjunc logic
This commit is contained in:
parent
a8443ef0cf
commit
0aeb0acd94
|
|
@ -628,6 +628,22 @@ public:
|
|||
return contents_are_solid(contents) || contents_are_sky(contents);
|
||||
}
|
||||
|
||||
bool contents_are_opaque(const contentflags_t &contents, bool transwater) const override
|
||||
{
|
||||
auto bits = contentflags_to_bits(contents).visible_contents();
|
||||
|
||||
if (bits.solid) return true;
|
||||
else if (bits.sky) return true;
|
||||
else if (bits.wall) return true;
|
||||
else if (bits.fence) return false;
|
||||
else if (bits.lava) return !transwater;
|
||||
else if (bits.slime) return !transwater;
|
||||
else if (bits.water) return !transwater;
|
||||
else if (bits.mist) return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
contentflags_t contents_remap_for_export(const contentflags_t &contents, remap_type_t type) const override
|
||||
{
|
||||
/*
|
||||
|
|
@ -1310,6 +1326,22 @@ struct gamedef_q2_t : public gamedef_t
|
|||
return contents_are_solid(contents) || contents_are_sky(contents);
|
||||
}
|
||||
|
||||
bool contents_are_opaque(const contentflags_t &contents, bool transwater) const override
|
||||
{
|
||||
int32_t c = contents.native;
|
||||
|
||||
if (!this->visible_contents(c))
|
||||
return false;
|
||||
|
||||
// it's visible..
|
||||
|
||||
if (c & Q2_CONTENTS_TRANSLUCENT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
contentflags_t contents_remap_for_export(const contentflags_t &contents, remap_type_t type) const override
|
||||
{
|
||||
// HACK: borrowing Q2_CONTENTS_MONSTER for func_detail_wall
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ maputil - utiltiy for working with Quake MAP files
|
|||
Synopsis
|
||||
========
|
||||
|
||||
**bsputil** [OPTION]... MAPFILE
|
||||
**maputil** MAPFILE [OPTION]...
|
||||
|
||||
Options
|
||||
=======
|
||||
|
|
|
|||
|
|
@ -298,6 +298,7 @@ struct gamedef_t
|
|||
virtual bool portal_can_see_through(
|
||||
const contentflags_t &contents0, const contentflags_t &contents1, bool transwater, bool transsky) const = 0;
|
||||
virtual bool contents_seals_map(const contentflags_t &contents) const = 0;
|
||||
virtual bool contents_are_opaque(const contentflags_t &contents, bool transwater) const = 0;
|
||||
enum class remap_type_t
|
||||
{
|
||||
brush,
|
||||
|
|
|
|||
|
|
@ -174,6 +174,7 @@ public:
|
|||
setting_int32 subdivide;
|
||||
setting_bool nofill;
|
||||
setting_bool nomerge;
|
||||
setting_bool mergeacrosswater;
|
||||
setting_bool noedgereuse;
|
||||
setting_bool noclip;
|
||||
setting_bool noskip;
|
||||
|
|
|
|||
|
|
@ -72,12 +72,14 @@ 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;
|
||||
|
||||
// TODO: make this configurable?
|
||||
if (qbsp_options.target_game->id != GAME_QUAKE_II) {
|
||||
// Q1: don't merge across water boundaries; ezQuake/nQuake 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;
|
||||
if (!qbsp_options.mergeacrosswater.value()) {
|
||||
// Q1: don't merge across water boundaries; ezQuake/nQuake 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))
|
||||
|
|
|
|||
|
|
@ -463,6 +463,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"},
|
||||
mergeacrosswater{this, "mergeacrosswater", false, &common_format_group, "merge faces that cross above and below water"},
|
||||
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"},
|
||||
|
|
|
|||
|
|
@ -143,21 +143,46 @@ static void FindEdgeVerts_BruteForce(
|
|||
* tjunc fixes. func_detail_wall is meant to act like a separate mesh,
|
||||
* so it shouldn't interact with solid.
|
||||
*/
|
||||
|
||||
static bool Welds(const contentflags_t &a, const contentflags_t &b)
|
||||
{
|
||||
// FIXME: no clipping same type?
|
||||
|
||||
// all types weld with themselves
|
||||
if (a.types_equal(b, qbsp_options.target_game))
|
||||
return true;
|
||||
|
||||
// detail wall only welds with detail wall
|
||||
if (qbsp_options.target_game->contents_are_detail_wall(a)
|
||||
|| qbsp_options.target_game->contents_are_detail_wall(b))
|
||||
return false;
|
||||
|
||||
// no need to weld translucent to opaque
|
||||
// (because they could have void behind them due to visblocking.
|
||||
// e.g. opaque water meeting solid)
|
||||
if (!qbsp_options.target_game->contents_are_opaque(a, qbsp_options.transwater.value())
|
||||
&& qbsp_options.target_game->contents_are_opaque(b, qbsp_options.transwater.value()))
|
||||
return false;
|
||||
if (!qbsp_options.target_game->contents_are_opaque(b, qbsp_options.transwater.value())
|
||||
&& qbsp_options.target_game->contents_are_opaque(a, qbsp_options.transwater.value()))
|
||||
return false;
|
||||
|
||||
// never weld with backfaces
|
||||
if (qbsp_options.target_game->contents_are_empty(a)
|
||||
|| qbsp_options.target_game->contents_are_empty(b))
|
||||
return false;
|
||||
|
||||
// otherwise, weld
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool HasTJuncInteraction(const face_t *f1, const face_t *f2)
|
||||
{
|
||||
// FIXME: handle func_detail_fence, func_detail_illusionary,
|
||||
// liquids? make sure a combination of solid + func_detail_wall
|
||||
// is treated as solid?
|
||||
|
||||
if (f1->contents.back.is_detail_wall(qbsp_options.target_game) &&
|
||||
!f2->contents.back.is_detail_wall(qbsp_options.target_game))
|
||||
return false;
|
||||
|
||||
if (f2->contents.back.is_detail_wall(qbsp_options.target_game) &&
|
||||
!f1->contents.back.is_detail_wall(qbsp_options.target_game))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return Welds(f1->contents.back, f2->contents.back);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -2122,3 +2122,195 @@ TEST_CASE("lq e3m4.map" * doctest::may_fail())
|
|||
const auto [bsp, bspx, prt] = LoadTestmap("LibreQuake/lq1/maps/src/e3/e3m4.map");
|
||||
CHECK(prt);
|
||||
}
|
||||
|
||||
TEST_CASE("q1_tjunc_matrix")
|
||||
{
|
||||
// TODO: test opaque water in q1 mode
|
||||
const auto [b, bspx, prt] = LoadTestmap("q1_tjunc_matrix.map", {"-mergeacrosswater"});
|
||||
const mbsp_t &bsp = b; // workaround clang not allowing capturing bindings in lambdas
|
||||
auto *game = bsp.loadversion->game;
|
||||
|
||||
CHECK(GAME_QUAKE == game->id);
|
||||
|
||||
const qvec3d face_midpoint_origin {-24, 0, 24};
|
||||
const qvec3d face_midpoint_to_tjunc {8, 0, 8};
|
||||
const qvec3d z_delta_to_next_face {0, 0, 64};
|
||||
const qvec3d x_delta_to_next_face {-64, 0, 0};
|
||||
|
||||
enum index_t : int {
|
||||
INDEX_SOLID = 0,
|
||||
INDEX_SOLID_DETAIL,
|
||||
INDEX_DETAIL_WALL,
|
||||
INDEX_DETAIL_FENCE,
|
||||
INDEX_DETAIL_FENCE_MIRRORINSIDE,
|
||||
INDEX_DETAIL_ILLUSIONARY,
|
||||
INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES,
|
||||
INDEX_WATER,
|
||||
INDEX_SKY
|
||||
};
|
||||
|
||||
auto has_tjunc = [&](index_t horizontal, index_t vertical) -> bool {
|
||||
const qvec3d face_midpoint = face_midpoint_origin
|
||||
+ (x_delta_to_next_face * static_cast<int>(horizontal))
|
||||
+ (z_delta_to_next_face * static_cast<int>(vertical));
|
||||
|
||||
auto *f = BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], face_midpoint);
|
||||
|
||||
const qvec3f tjunc_location = qvec3f(face_midpoint + face_midpoint_to_tjunc);
|
||||
|
||||
for (int i = 0; i < f->numedges; ++i) {
|
||||
if (Face_PointAtIndex(&bsp, f, i) == tjunc_location) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
{
|
||||
INFO("INDEX_SOLID horizontal - welds with anything opaque except detail_wall");
|
||||
CHECK( has_tjunc(INDEX_SOLID, INDEX_SOLID));
|
||||
CHECK( has_tjunc(INDEX_SOLID, INDEX_SOLID_DETAIL));
|
||||
CHECK(!has_tjunc(INDEX_SOLID, INDEX_DETAIL_WALL));
|
||||
CHECK(!has_tjunc(INDEX_SOLID, INDEX_DETAIL_FENCE));
|
||||
CHECK(!has_tjunc(INDEX_SOLID, INDEX_DETAIL_FENCE_MIRRORINSIDE));
|
||||
CHECK(!has_tjunc(INDEX_SOLID, INDEX_DETAIL_ILLUSIONARY));
|
||||
CHECK(!has_tjunc(INDEX_SOLID, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
|
||||
// "-mergeacrosswater" is needed to prevent a weld between transparent water and solid
|
||||
CHECK(!has_tjunc(INDEX_SOLID, INDEX_WATER));
|
||||
CHECK( has_tjunc(INDEX_SOLID, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_SOLID_DETAIL horizontal - welds with anything opaque except detail_wall");
|
||||
CHECK( has_tjunc(INDEX_SOLID_DETAIL, INDEX_SOLID));
|
||||
CHECK( has_tjunc(INDEX_SOLID_DETAIL, INDEX_SOLID_DETAIL));
|
||||
CHECK(!has_tjunc(INDEX_SOLID_DETAIL, INDEX_DETAIL_WALL));
|
||||
CHECK(!has_tjunc(INDEX_SOLID_DETAIL, INDEX_DETAIL_FENCE));
|
||||
CHECK(!has_tjunc(INDEX_SOLID_DETAIL, INDEX_DETAIL_FENCE_MIRRORINSIDE));
|
||||
CHECK(!has_tjunc(INDEX_SOLID_DETAIL, INDEX_DETAIL_ILLUSIONARY));
|
||||
CHECK(!has_tjunc(INDEX_SOLID_DETAIL, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
|
||||
// see INDEX_SOLID, INDEX_WATER explanation
|
||||
CHECK(!has_tjunc(INDEX_SOLID_DETAIL, INDEX_WATER));
|
||||
CHECK( has_tjunc(INDEX_SOLID_DETAIL, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_DETAIL_WALL horizontal");
|
||||
// solid cuts a hole in detail_wall
|
||||
CHECK( has_tjunc(INDEX_DETAIL_WALL, INDEX_SOLID));
|
||||
// solid detail cuts a hole in detail_wall
|
||||
CHECK( has_tjunc(INDEX_DETAIL_WALL, INDEX_SOLID_DETAIL));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_WALL, INDEX_DETAIL_WALL));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_DETAIL_FENCE));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_DETAIL_FENCE_MIRRORINSIDE));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_DETAIL_ILLUSIONARY));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
|
||||
// see INDEX_SOLID, INDEX_WATER explanation
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_WATER));
|
||||
// sky cuts a hole in detail_wall
|
||||
CHECK( has_tjunc(INDEX_DETAIL_WALL, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_DETAIL_FENCE horizontal");
|
||||
// solid cuts a hole in fence
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE, INDEX_SOLID));
|
||||
// solid detail cuts a hole in fence
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE, INDEX_SOLID_DETAIL));
|
||||
// detail wall cuts a hole in fence
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE, INDEX_DETAIL_WALL));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE, INDEX_DETAIL_FENCE));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE, INDEX_DETAIL_FENCE_MIRRORINSIDE));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE, INDEX_DETAIL_ILLUSIONARY));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
|
||||
// weld because both are translucent
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE, INDEX_WATER));
|
||||
// sky cuts a hole in fence
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_DETAIL_FENCE_MIRRORINSIDE horizontal");
|
||||
// solid cuts a hole in fence
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE_MIRRORINSIDE, INDEX_SOLID));
|
||||
// solid detail cuts a hole in fence
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE_MIRRORINSIDE, INDEX_SOLID_DETAIL));
|
||||
// detail wall cuts a hole in fence
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE_MIRRORINSIDE, INDEX_DETAIL_WALL));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE_MIRRORINSIDE, INDEX_DETAIL_FENCE));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE_MIRRORINSIDE, INDEX_DETAIL_FENCE_MIRRORINSIDE));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE_MIRRORINSIDE, INDEX_DETAIL_ILLUSIONARY));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE_MIRRORINSIDE, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
|
||||
// weld because both are translucent
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE_MIRRORINSIDE, INDEX_WATER));
|
||||
// sky cuts a hole in fence
|
||||
CHECK( has_tjunc(INDEX_DETAIL_FENCE_MIRRORINSIDE, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_DETAIL_ILLUSIONARY horizontal");
|
||||
// solid cuts a hole in illusionary
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY, INDEX_SOLID));
|
||||
// solid detail cuts a hole in illusionary
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY, INDEX_SOLID_DETAIL));
|
||||
// detail wall cuts a hole in illusionary
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY, INDEX_DETAIL_WALL));
|
||||
// fence and illusionary are both translucent, so weld
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY, INDEX_DETAIL_FENCE));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY, INDEX_DETAIL_FENCE_MIRRORINSIDE));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY, INDEX_DETAIL_ILLUSIONARY));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
|
||||
// weld because both are translucent
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY, INDEX_WATER));
|
||||
// sky cuts a hole in illusionary
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES horizontal");
|
||||
// solid cuts a hole in illusionary
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES, INDEX_SOLID));
|
||||
// solid detail cuts a hole in illusionary
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES, INDEX_SOLID_DETAIL));
|
||||
// detail wall cuts a hole in illusionary
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES, INDEX_DETAIL_WALL));
|
||||
// fence and illusionary are both translucent, so weld
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES, INDEX_DETAIL_FENCE));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES, INDEX_DETAIL_FENCE_MIRRORINSIDE));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES, INDEX_DETAIL_ILLUSIONARY));
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
|
||||
// weld because both are translucent
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES, INDEX_WATER));
|
||||
// sky cuts a hole in illusionary
|
||||
CHECK( has_tjunc(INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_WATER horizontal");
|
||||
// solid cuts a hole in water
|
||||
CHECK( has_tjunc(INDEX_WATER, INDEX_SOLID));
|
||||
// solid detail cuts a hole in illusionary
|
||||
CHECK( has_tjunc(INDEX_WATER, INDEX_SOLID_DETAIL));
|
||||
// detail wall cuts a hole in water
|
||||
CHECK( has_tjunc(INDEX_WATER, INDEX_DETAIL_WALL));
|
||||
CHECK( has_tjunc(INDEX_WATER, INDEX_DETAIL_FENCE));
|
||||
CHECK( has_tjunc(INDEX_WATER, INDEX_DETAIL_FENCE_MIRRORINSIDE));
|
||||
CHECK( has_tjunc(INDEX_WATER, INDEX_DETAIL_ILLUSIONARY));
|
||||
CHECK( has_tjunc(INDEX_WATER, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
|
||||
CHECK( has_tjunc(INDEX_WATER, INDEX_WATER));
|
||||
CHECK( has_tjunc(INDEX_WATER, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_SKY horizontal");
|
||||
CHECK( has_tjunc(INDEX_SKY, INDEX_SOLID));
|
||||
CHECK( has_tjunc(INDEX_SKY, INDEX_SOLID_DETAIL));
|
||||
CHECK(!has_tjunc(INDEX_SKY, INDEX_DETAIL_WALL));
|
||||
CHECK(!has_tjunc(INDEX_SKY, INDEX_DETAIL_FENCE));
|
||||
CHECK(!has_tjunc(INDEX_SKY, INDEX_DETAIL_FENCE_MIRRORINSIDE));
|
||||
CHECK(!has_tjunc(INDEX_SKY, INDEX_DETAIL_ILLUSIONARY));
|
||||
CHECK(!has_tjunc(INDEX_SKY, INDEX_DETAIL_ILLUSIONARY_NOCLIPFACES));
|
||||
CHECK(!has_tjunc(INDEX_SKY, INDEX_WATER));
|
||||
CHECK( has_tjunc(INDEX_SKY, INDEX_SKY));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -868,7 +868,7 @@ TEST_CASE("q2_mist_transwater" * doctest::test_suite("testmaps_q2"))
|
|||
CHECK(Face_Winding(&bsp, down_faces[0]).directional_equal(top_of_water_dn));
|
||||
}
|
||||
|
||||
TEST_CASE("q2_tjunc_matrix" * doctest::test_suite("testmaps_q2") * doctest::may_fail())
|
||||
TEST_CASE("q2_tjunc_matrix" * doctest::test_suite("testmaps_q2"))
|
||||
{
|
||||
const auto [b, bspx, prt] = LoadTestmapQ2("q2_tjunc_matrix.map");
|
||||
const mbsp_t &bsp = b; // workaround clang not allowing capturing bindings in lambdas
|
||||
|
|
@ -911,16 +911,20 @@ TEST_CASE("q2_tjunc_matrix" * doctest::test_suite("testmaps_q2") * doctest::may_
|
|||
};
|
||||
|
||||
{
|
||||
INFO("INDEX_DETAIL_WALL horizontal - only welds with itself");
|
||||
INFO("INDEX_DETAIL_WALL horizontal");
|
||||
CHECK( has_tjunc(INDEX_DETAIL_WALL, INDEX_DETAIL_WALL));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_SOLID));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_SOLID_DETAIL));
|
||||
// this one is tricky - the solid cuts a hole in the top
|
||||
// that hole (the detail_wall faces) are what weld with the side
|
||||
CHECK( has_tjunc(INDEX_DETAIL_WALL, INDEX_SOLID));
|
||||
// same as INDEX_DETAIL_WALL, INDEX_SOLID
|
||||
CHECK( has_tjunc(INDEX_DETAIL_WALL, INDEX_SOLID_DETAIL));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_TRANSPARENT_WATER));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_OPAQUE_WATER));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_OPAQUE_MIST));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_TRANSPARENT_WINDOW));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_OPAQUE_AUX));
|
||||
CHECK(!has_tjunc(INDEX_DETAIL_WALL, INDEX_SKY));
|
||||
// same as INDEX_DETAIL_WALL, INDEX_SOLID
|
||||
CHECK( has_tjunc(INDEX_DETAIL_WALL, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -950,66 +954,83 @@ TEST_CASE("q2_tjunc_matrix" * doctest::test_suite("testmaps_q2") * doctest::may_
|
|||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_TRANSPARENT_WATER horizontal - only welds with itself");
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_DETAIL_WALL));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_SOLID));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_SOLID_DETAIL));
|
||||
INFO("INDEX_TRANSPARENT_WATER horizontal");
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_DETAIL_WALL));
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_SOLID));
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_SOLID_DETAIL));
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_TRANSPARENT_WATER));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_OPAQUE_WATER));
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_OPAQUE_WATER));
|
||||
// water is stronger than mist, so cuts away the bottom face of the mist
|
||||
// the top face of the water then doesn't need to weld because
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_OPAQUE_MIST));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_TRANSPARENT_WINDOW));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_OPAQUE_AUX));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_SKY));
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_TRANSPARENT_WINDOW));
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_OPAQUE_AUX));
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WATER, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_OPAQUE_WATER horizontal - same as INDEX_SOLID");
|
||||
CHECK(!has_tjunc(INDEX_OPAQUE_WATER, INDEX_DETAIL_WALL));
|
||||
INFO("INDEX_OPAQUE_WATER horizontal");
|
||||
// detail wall is stronger than water, so cuts a hole and the water then welds with itself
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_WATER, INDEX_DETAIL_WALL));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_WATER, INDEX_SOLID));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_WATER, INDEX_SOLID_DETAIL));
|
||||
CHECK(!has_tjunc(INDEX_OPAQUE_WATER, INDEX_TRANSPARENT_WATER));
|
||||
// welds because opaque water and translucent don't get a face between them
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_WATER, INDEX_TRANSPARENT_WATER));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_WATER, INDEX_OPAQUE_WATER));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_WATER, INDEX_OPAQUE_MIST));
|
||||
CHECK(!has_tjunc(INDEX_OPAQUE_WATER, INDEX_TRANSPARENT_WINDOW));
|
||||
// window is stronger and cuts a hole in the water
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_WATER, INDEX_TRANSPARENT_WINDOW));
|
||||
// same with aux
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_WATER, INDEX_OPAQUE_AUX));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_WATER, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_OPAQUE_MIST horizontal - same as INDEX_SOLID");
|
||||
CHECK(!has_tjunc(INDEX_OPAQUE_MIST, INDEX_DETAIL_WALL));
|
||||
INFO("INDEX_OPAQUE_MIST horizontal");
|
||||
// detail wall is stronger, cuts mist
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_MIST, INDEX_DETAIL_WALL));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_MIST, INDEX_SOLID));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_MIST, INDEX_SOLID_DETAIL));
|
||||
CHECK(!has_tjunc(INDEX_OPAQUE_MIST, INDEX_TRANSPARENT_WATER));
|
||||
// water is stronger, cuts mist
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_MIST, INDEX_TRANSPARENT_WATER));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_MIST, INDEX_OPAQUE_WATER));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_MIST, INDEX_OPAQUE_MIST));
|
||||
CHECK(!has_tjunc(INDEX_OPAQUE_MIST, INDEX_TRANSPARENT_WINDOW));
|
||||
// window is stronger, cuts mist
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_MIST, INDEX_TRANSPARENT_WINDOW));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_MIST, INDEX_OPAQUE_AUX));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_MIST, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_TRANSPARENT_WINDOW horizontal - only welds with itself");
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_DETAIL_WALL));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_SOLID));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_SOLID_DETAIL));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_TRANSPARENT_WATER));
|
||||
INFO("INDEX_TRANSPARENT_WINDOW horizontal");
|
||||
// detail wall is stronger than window, cuts a hole in the window, so window
|
||||
// tjuncs with itself
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_DETAIL_WALL));
|
||||
// solid cuts a hole in the window
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_SOLID));
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_SOLID_DETAIL));
|
||||
// translucent window and translucent water weld
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_TRANSPARENT_WATER));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_OPAQUE_WATER));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_OPAQUE_MIST));
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_TRANSPARENT_WINDOW));
|
||||
// note, aux is lower priority than window, so bottom face of aux gets cut away
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_OPAQUE_AUX));
|
||||
CHECK(!has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_SKY));
|
||||
// sky cuts hole in window
|
||||
CHECK( has_tjunc(INDEX_TRANSPARENT_WINDOW, INDEX_SKY));
|
||||
}
|
||||
|
||||
{
|
||||
INFO("INDEX_OPAQUE_AUX horizontal - same as INDEX_SOLID");
|
||||
CHECK(!has_tjunc(INDEX_OPAQUE_AUX, INDEX_DETAIL_WALL));
|
||||
INFO("INDEX_OPAQUE_AUX horizontal");
|
||||
// detail_wall is higher priority, cuts a hole in aux, which welds with itself
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_AUX, INDEX_DETAIL_WALL));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_AUX, INDEX_SOLID));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_AUX, INDEX_SOLID_DETAIL));
|
||||
CHECK(!has_tjunc(INDEX_OPAQUE_AUX, INDEX_TRANSPARENT_WATER));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_AUX, INDEX_OPAQUE_WATER));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_AUX, INDEX_OPAQUE_MIST));
|
||||
CHECK(!has_tjunc(INDEX_OPAQUE_AUX, INDEX_TRANSPARENT_WINDOW));
|
||||
// window is stronger, cuts a hole which causes aux to weld
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_AUX, INDEX_TRANSPARENT_WINDOW));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_AUX, INDEX_OPAQUE_AUX));
|
||||
CHECK( has_tjunc(INDEX_OPAQUE_AUX, INDEX_SKY));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue