diff --git a/common/bspfile.cc b/common/bspfile.cc index 215f4199..9662ec5b 100644 --- a/common/bspfile.cc +++ b/common/bspfile.cc @@ -1227,7 +1227,8 @@ struct gamedef_q2_t : public gamedef_t // windows don't generate inside faces return false; } - return true; + // other types get mirrored by default, unless we override it with mirror_inside + return brushcontents.mirror_inside.value_or(true); } return true; } diff --git a/testmaps/qbsp_q2_mirrorinside.map b/testmaps/qbsp_q2_mirrorinside.map new file mode 100644 index 00000000..632abd23 --- /dev/null +++ b/testmaps/qbsp_q2_mirrorinside.map @@ -0,0 +1,90 @@ +// Game: Quake 2 +// Format: Quake2 (Valve) +// entity 0 +{ +"mapversion" "220" +"classname" "worldspawn" +"_tb_textures" "textures/e1u1;textures/e1u2;textures/e1u3;textures/e1u4;textures/e2u1;textures/e2u2;textures/e2u3;textures/e3u1;textures/e3u2;textures/e3u3" +// brush 0 +{ +( -176 -256 64 ) ( -176 -255 64 ) ( -176 -256 65 ) e1u1/ggrat4_2 [ 0 1.0000000000000002 0 -16 ] [ 0 0 -1.0000000000000002 -32 ] 0 1 1 +( -176 -432 64 ) ( -176 -432 65 ) ( -175 -432 64 ) e1u1/ggrat4_2 [ -1 0 0 -16 ] [ 0 0 -1 -32 ] 0 1 1 +( -176 -256 96 ) ( -175 -256 96 ) ( -176 -255 96 ) e1u1/ggrat4_2 [ -1.0000000000000002 0 0 -16 ] [ 0 1.0000000000000002 0 -48 ] 0 1 1 +( -160 192 352 ) ( -160 193 352 ) ( -159 192 352 ) e1u1/ggrat4_2 [ -1.0000000000000002 0 0 -16 ] [ 0 -1.0000000000000002 0 -80 ] 0 1 1 +( -160 176 80 ) ( -159 176 80 ) ( -160 176 81 ) e1u1/ggrat4_2 [ -1 0 0 -16 ] [ 0 0 -1 -32 ] 0 1 1 +( -160 192 80 ) ( -160 192 81 ) ( -160 193 80 ) e1u1/ggrat4_2 [ 0 -1.0000000000000002 0 64 ] [ 0 0 -1.0000000000000002 -32 ] 0 1 1 +} +// brush 1 +{ +( -160 176 88 ) ( -160 177 88 ) ( -160 176 89 ) e1u1/ggrat4_2 [ 0 1.0000000000000002 0 -32 ] [ 0 0 -1.0000000000000002 -32 ] 0 1 1 +( -160 176 88 ) ( -160 176 89 ) ( -159 176 88 ) e1u1/ggrat4_2 [ -1 0 0 -16 ] [ 0 0 -1 -32 ] 0 1 1 +( -160 176 96 ) ( -159 176 96 ) ( -160 177 96 ) e1u1/ggrat4_2 [ -1.0000000000000002 0 0 -16 ] [ 0 1.0000000000000002 0 -40 ] 0 1 1 +( 288 192 352 ) ( 288 193 352 ) ( 289 192 352 ) e1u1/ggrat4_2 [ -1.0000000000000002 0 0 -16 ] [ 0 -1.0000000000000002 0 48 ] 0 1 1 +( 288 192 96 ) ( 289 192 96 ) ( 288 192 97 ) e1u1/ggrat4_2 [ -1 0 0 -16 ] [ 0 0 -1 -32 ] 0 1 1 +( 288 192 96 ) ( 288 192 97 ) ( 288 193 96 ) e1u1/ggrat4_2 [ 0 -1.0000000000000002 0 0 ] [ 0 0 -1.0000000000000002 -32 ] 0 1 1 +} +// brush 2 +{ +( -160 -112 96 ) ( -160 -111 96 ) ( -160 -112 97 ) e1u1/florr1_8 [ 0 1 0 -16 ] [ 0 0 -1 0 ] 0 1 1 +( -80 -432 80 ) ( -81 -432 80 ) ( -80 -432 81 ) e1u1/florr1_8 [ -1 0 0 16 ] [ 0 0 -1 0 ] 180 1 1 +( -80 -432 80 ) ( -80 -431 80 ) ( -81 -432 80 ) e1u1/florr1_8 [ 1 0 0 -16 ] [ 0 -1 0 16 ] 180 1 1 +( -160 -112 96 ) ( -161 -112 96 ) ( -160 -111 96 ) e1u1/florr1_8 [ -1 0 0 16 ] [ 0 -1 0 16 ] 180 1 1 +( -160 176 96 ) ( -160 176 97 ) ( -161 176 96 ) e1u1/florr1_8 [ 1 0 0 -16 ] [ 0 0 -1 0 ] 180 1 1 +( 288 -432 80 ) ( 288 -432 81 ) ( 288 -431 80 ) e1u1/florr1_8 [ 0 -1 0 16 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 3 +{ +( -160 -448 88 ) ( -160 -447 88 ) ( -160 -448 89 ) e1u1/ggrat4_2 [ 0 1 0 0 ] [ 0 0 -1 -32 ] 0 1 1 +( -160 -448 88 ) ( -160 -448 89 ) ( -159 -448 88 ) e1u1/ggrat4_2 [ -1.0000000000000002 0 0 -32 ] [ 0 0 -1.0000000000000002 -32 ] 0 1 1 +( -160 -448 96 ) ( -159 -448 96 ) ( -160 -447 96 ) e1u1/ggrat4_2 [ 0 1.0000000000000002 0 0 ] [ 1.0000000000000002 0 0 -32 ] 0 1 1 +( 288 -432 352 ) ( 288 -431 352 ) ( 289 -432 352 ) e1u1/ggrat4_2 [ 0 1.0000000000000002 0 0 ] [ -1.0000000000000002 0 0 -96 ] 0 1 1 +( 288 -432 96 ) ( 289 -432 96 ) ( 288 -432 97 ) e1u1/ggrat4_2 [ 1.0000000000000002 0 0 -80 ] [ 0 0 -1.0000000000000002 -32 ] 0 1 1 +( 288 -432 96 ) ( 288 -432 97 ) ( 288 -431 96 ) e1u1/ggrat4_2 [ 0 1 0 0 ] [ 0 0 -1 -32 ] 0 1 1 +} +// brush 4 +{ +( -160 -256 352 ) ( -160 -255 352 ) ( -160 -256 353 ) e1u1/florr1_8 [ 0 0 -1.0000000000000002 0 ] [ 0 -1.0000000000000002 0 0 ] 180 1 1 +( 288 -432 360 ) ( 288 -432 361 ) ( 289 -432 360 ) e1u1/florr1_8 [ -1.0000000000000002 0 0 0 ] [ 0 0 1.0000000000000002 -16 ] 180 1 1 +( -160 -256 352 ) ( -159 -256 352 ) ( -160 -255 352 ) e1u1/florr1_8 [ -1 0 0 0 ] [ 0 -1 0 0 ] 180 1 1 +( 288 176 368 ) ( 288 177 368 ) ( 289 176 368 ) e1u1/florr1_8 [ -1 0 0 0 ] [ 0 -1 0 0 ] 180 1 1 +( 288 176 360 ) ( 289 176 360 ) ( 288 176 361 ) e1u1/florr1_8 [ -1.0000000000000002 0 0 0 ] [ 0 0 1.0000000000000002 -16 ] 180 1 1 +( 288 176 360 ) ( 288 176 361 ) ( 288 177 360 ) e1u1/florr1_8 [ 0 0 1.0000000000000002 0 ] [ 0 -1.0000000000000002 0 0 ] 180 1 1 +} +// brush 5 +{ +( 288 192 80 ) ( 288 193 80 ) ( 288 192 81 ) e1u1/ggrat4_2 [ 0 1 0 0 ] [ 0 0 -1 -32 ] 0 1 1 +( 304 -432 64 ) ( 303 -432 64 ) ( 304 -432 65 ) e1u1/ggrat4_2 [ -1 0 0 16 ] [ 0 0 -1 -32 ] 180 1 1 +( 304 -256 96 ) ( 304 -255 96 ) ( 303 -256 96 ) e1u1/ggrat4_2 [ 1 0 0 -16 ] [ 0 -1 0 0 ] 180 1 1 +( 304 -256 352 ) ( 303 -256 352 ) ( 304 -255 352 ) e1u1/ggrat4_2 [ 1 0 0 -16 ] [ 0 -1 0 0 ] 180 1 1 +( 288 176 80 ) ( 288 176 81 ) ( 287 176 80 ) e1u1/ggrat4_2 [ 1 0 0 -16 ] [ 0 0 -1 -32 ] 180 1 1 +( 304 -256 64 ) ( 304 -256 65 ) ( 304 -255 64 ) e1u1/ggrat4_2 [ 0 -1 0 0 ] [ 0 0 -1 -32 ] 0 1 1 +} +// brush 6 +{ +( 32 -80 112 ) ( 32 -79 112 ) ( 32 -80 113 ) e1u1/brwater [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 64 0 100 +( 32 -80 112 ) ( 32 -80 113 ) ( 33 -80 112 ) e1u1/brwater [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 64 0 100 +( 32 -80 112 ) ( 33 -80 112 ) ( 32 -79 112 ) e1u1/brwater [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 64 0 100 +( 112 32 192 ) ( 112 33 192 ) ( 113 32 192 ) e1u1/brwater [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 64 0 100 +( 112 32 128 ) ( 113 32 128 ) ( 112 32 129 ) e1u1/brwater [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 64 0 100 +( 112 32 128 ) ( 112 32 129 ) ( 112 33 128 ) e1u1/brwater [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 64 0 100 +} +} +// entity 1 +{ +"classname" "info_player_start" +"origin" "-88 -112 120" +} +// entity 2 +{ +"classname" "func_group" +"_mirrorinside" "0" +// brush 0 +{ +( 32 -272 112 ) ( 32 -271 112 ) ( 32 -272 113 ) e1u1/brwater [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 64 0 100 +( 32 -272 112 ) ( 32 -272 113 ) ( 33 -272 112 ) e1u1/brwater [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 64 0 100 +( 32 -272 112 ) ( 33 -272 112 ) ( 32 -271 112 ) e1u1/brwater [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 64 0 100 +( 112 -160 192 ) ( 112 -159 192 ) ( 113 -160 192 ) e1u1/brwater [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 64 0 100 +( 112 -160 128 ) ( 113 -160 128 ) ( 112 -160 129 ) e1u1/brwater [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 64 0 100 +( 112 -160 128 ) ( 112 -160 129 ) ( 112 -159 128 ) e1u1/brwater [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 64 0 100 +} +} diff --git a/tests/test_qbsp_q2.cc b/tests/test_qbsp_q2.cc index 938b9da8..1eef1618 100644 --- a/tests/test_qbsp_q2.cc +++ b/tests/test_qbsp_q2.cc @@ -501,3 +501,22 @@ TEST_CASE("q2_door" * doctest::test_suite("testmaps_q2")) { CHECK(bmodel_tight_bounds.mins() == bsp.dmodels[1].mins); CHECK(bmodel_tight_bounds.maxs() == bsp.dmodels[1].maxs); } + +TEST_CASE("q2_mirrorinside" * doctest::test_suite("testmaps_q2")) +{ + const auto [bsp, bspx, prt] = LoadTestmapQ2("qbsp_q2_mirrorinside.map"); + + { + INFO("mist is two sided by default"); + const qvec3d mist_pos{32, -28, 156}; + CHECK_VECTORS_UNOREDERED_EQUAL(TexNames(bsp, BSP_FindFacesAtPoint(&bsp, &bsp.dmodels[0], mist_pos)), + std::vector({"e1u1/brwater", "e1u1/brwater"})); + } + + { + INFO("_mirrorinside 0 disables the inside faces on mist"); + const qvec3d mist_mirrorinside0_pos{32, -224, 156}; + CHECK_VECTORS_UNOREDERED_EQUAL(TexNames(bsp, BSP_FindFacesAtPoint(&bsp, &bsp.dmodels[0], mist_mirrorinside0_pos)), + std::vector({"e1u1/brwater"})); + } +}