diff --git a/testmaps/q2_light_low_luxel_res.map b/testmaps/q2_light_low_luxel_res.map new file mode 100644 index 00000000..db53a0ab --- /dev/null +++ b/testmaps/q2_light_low_luxel_res.map @@ -0,0 +1,109 @@ +// Game: Quake 2 +// Format: Quake2 (Valve) +// entity 0 +{ +"classname" "worldspawn" +"_tb_textures" "textures/e1u1" +// brush 0 +{ +( 1840 692 -1000 ) ( 1840 693 -1000 ) ( 1840 692 -999 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2156 692 -1000 ) ( 2156 692 -999 ) ( 2157 692 -1000 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2156 692 -1020 ) ( 2157 692 -1020 ) ( 2156 693 -1020 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 708 -880 ) ( 2176 709 -880 ) ( 2177 708 -880 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 708 -996 ) ( 2177 708 -996 ) ( 2176 708 -995 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2368 708 -996 ) ( 2368 708 -995 ) ( 2368 709 -996 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +} +// brush 1 +{ +( 1840 692 -1000 ) ( 1840 693 -1000 ) ( 1840 692 -999 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2176 908 -996 ) ( 2176 908 -995 ) ( 2177 908 -996 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2156 692 -1020 ) ( 2157 692 -1020 ) ( 2156 693 -1020 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 708 -880 ) ( 2176 709 -880 ) ( 2177 708 -880 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 912 -996 ) ( 2177 912 -996 ) ( 2176 912 -995 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2368 708 -996 ) ( 2368 708 -995 ) ( 2368 709 -996 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +} +// brush 2 +{ +( 1840 692 -860 ) ( 1840 693 -860 ) ( 1840 692 -859 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2176 708 -856 ) ( 2176 708 -855 ) ( 2177 708 -856 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2156 692 -880 ) ( 2157 692 -880 ) ( 2156 693 -880 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 708 -876 ) ( 2176 709 -876 ) ( 2177 708 -876 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 908 -856 ) ( 2177 908 -856 ) ( 2176 908 -855 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2368 708 -856 ) ( 2368 708 -855 ) ( 2368 709 -856 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +} +// brush 3 +{ +( 2368 692 -1000 ) ( 2368 693 -1000 ) ( 2368 692 -999 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2180 708 -996 ) ( 2180 708 -995 ) ( 2181 708 -996 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2160 692 -1020 ) ( 2161 692 -1020 ) ( 2160 693 -1020 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2180 708 -880 ) ( 2180 709 -880 ) ( 2181 708 -880 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2180 908 -996 ) ( 2181 908 -996 ) ( 2180 908 -995 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2372 708 -996 ) ( 2372 708 -995 ) ( 2372 709 -996 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +} +// brush 4 +{ +( 1836 692 -1000 ) ( 1836 693 -1000 ) ( 1836 692 -999 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 1648 708 -996 ) ( 1648 708 -995 ) ( 1649 708 -996 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 1628 692 -1020 ) ( 1629 692 -1020 ) ( 1628 693 -1020 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 1648 708 -880 ) ( 1648 709 -880 ) ( 1649 708 -880 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 1648 908 -996 ) ( 1649 908 -996 ) ( 1648 908 -995 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 1840 708 -996 ) ( 1840 708 -995 ) ( 1840 709 -996 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +} +// brush 5 +{ +( 1840 692 -1004 ) ( 1840 693 -1004 ) ( 1840 692 -1003 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2176 708 -1000 ) ( 2176 708 -999 ) ( 2177 708 -1000 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2156 692 -1024 ) ( 2157 692 -1024 ) ( 2156 693 -1024 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 708 -1020 ) ( 2176 709 -1020 ) ( 2177 708 -1020 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 908 -1000 ) ( 2177 908 -1000 ) ( 2176 908 -999 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2208 816 -1020 ) ( 2208 768 -1020 ) ( 2208 768 -892 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +} +// brush 6 +{ +( 2240 784 -1020 ) ( 2240 800 -1020 ) ( 2240 800 -892 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2176 708 -1000 ) ( 2176 708 -999 ) ( 2177 708 -1000 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2156 692 -1024 ) ( 2157 692 -1024 ) ( 2156 693 -1024 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 708 -1020 ) ( 2176 709 -1020 ) ( 2177 708 -1020 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 908 -1000 ) ( 2177 908 -1000 ) ( 2176 908 -999 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2368 708 -1000 ) ( 2368 708 -999 ) ( 2368 709 -1000 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +} +// brush 7 +{ +( 2208 816 -1020 ) ( 2208 768 -892 ) ( 2208 768 -1020 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2176 708 -1000 ) ( 2176 708 -999 ) ( 2177 708 -1000 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2156 692 -1024 ) ( 2157 692 -1024 ) ( 2156 693 -1024 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 708 -1020 ) ( 2176 709 -1020 ) ( 2177 708 -1020 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 +( 2176 908 -1000 ) ( 2177 908 -1000 ) ( 2176 908 -999 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +( 2240 784 -1020 ) ( 2240 800 -892 ) ( 2240 800 -1020 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 +} +} +// entity 1 +{ +"classname" "func_group" +"_minlight" "2.0" +"_minlight_color" "1 0.8 0" +// brush 0 +{ +( 2160 712 -964 ) ( 2156 708 -960 ) ( 2156 708 -976 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 134217728 0 0 +( 2156 708 -960 ) ( 2172 708 -960 ) ( 2172 708 -976 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 134217728 0 0 +( 2156 708 -976 ) ( 2172 708 -976 ) ( 2168 712 -972 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 134217728 0 0 +( 2168 712 -964 ) ( 2172 708 -960 ) ( 2156 708 -960 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 0.5 0.5 134217728 0 0 +( 2168 712 -972 ) ( 2168 712 -964 ) ( 2160 712 -964 ) e1u1/color1_2 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 134217728 0 0 +( 2172 708 -976 ) ( 2172 708 -960 ) ( 2168 712 -964 ) e1u1/color1_2 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 0.5 0.5 134217728 0 0 +} +// brush 1 +{ +( 2134 712 -964 ) ( 2134 708 -964 ) ( 2134 708 -972 ) e1u1/color1_2 [ -0.7071067811865532 1 0 9.931641 ] [ 0 0 -1 0 ] 9.815298 0.5 0.5 134217728 0 0 +( 2134 708 -964 ) ( 2142 708 -964 ) ( 2142 708 -972 ) e1u1/color1_2 [ 1.9999999999999998 0 0 0 ] [ 0 0 -1.9999999999999998 -16 ] 0 0.5 0.5 134217728 0 0 +( 2142 708 -972 ) ( 2142 712 -972 ) ( 2134 712 -972 ) e1u1/color1_2 [ 1 0 0 52 ] [ 4.3012913977543575e-18 -1 0.707106781186553 30.615479 ] 0 0.5 0.5 134217728 0 0 +( 2134 712 -964 ) ( 2142 712 -964 ) ( 2142 708 -964 ) e1u1/color1_2 [ 1 0 0 52 ] [ -4.3012913977543575e-18 -1 -0.707106781186553 -19.301758 ] 0 0.5 0.5 134217728 0 0 +( 2142 712 -972 ) ( 2142 712 -964 ) ( 2134 712 -964 ) e1u1/color1_2 [ 1 0 0 52 ] [ 0 0 -1 0 ] 0 0.5 0.5 134217728 0 0 +( 2142 708 -964 ) ( 2142 712 -964 ) ( 2142 712 -972 ) e1u1/color1_2 [ 0.7071067811865532 1 0 -21.245605 ] [ 0 0 -1 0 ] 9.815298 0.5 0.5 134217728 0 0 +} +} +// entity 2 +{ +"classname" "info_player_start" +"origin" "2164 788 -996" +"angle" "270" +} diff --git a/tests/test_ltface.cc b/tests/test_ltface.cc index 59ea927b..4ad6f69e 100644 --- a/tests/test_ltface.cc +++ b/tests/test_ltface.cc @@ -240,19 +240,30 @@ static void CheckFaceLuxelsNonBlack(const mbsp_t &bsp, const mface_t &face) } static void CheckFaceLuxelAtPoint(const mbsp_t *bsp, const dmodelh2_t *model, const qvec3b &expected_color, - const qvec3d &point, const qvec3d &normal = {0, 0, 0}, const std::vector *lit = nullptr) + const qvec3d &point, const qvec3d &normal = {0, 0, 0}, const std::vector *lit = nullptr, + const bspxentries_t *bspx = nullptr) { auto *face = BSP_FindFaceAtPoint(bsp, model, point, normal); REQUIRE(face); - // FIXME: assumes no DECOUPLED_LM lump + faceextents_t extents; + int offset; - const faceextents_t extents(*face, *bsp, LMSCALE_DEFAULT); + if (bspx && bspx->find("DECOUPLED_LM") != bspx->end()) { + auto lm_info = BSPX_DecoupledLM(*bspx, Face_GetNum(bsp, face)); + extents = faceextents_t(*face, *bsp, lm_info.lmwidth, lm_info.lmheight, lm_info.world_to_lm_space); + offset = lm_info.offset; + } else { + // vanilla lightmap + extents = faceextents_t(*face, *bsp, LMSCALE_DEFAULT); + offset = face->lightofs; + } const auto coord = extents.worldToLMCoord(point); - const qvec3b sample = LM_Sample(bsp, lit, extents, face->lightofs, qvec2i(coord)); - INFO("sample ", coord[0], ", ", coord[1]); + const qvec3b sample = LM_Sample(bsp, lit, extents, offset, qvec2i(coord)); + INFO("world point: ", point); + INFO("lm coord: ", coord[0], ", ", coord[1]); CHECK(sample == expected_color); } @@ -642,3 +653,18 @@ TEST_CASE("q1_lightignore" * doctest::may_fail()) CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {55, 69, 83}, {-128, 144, 32}, {0, 0, 1}, &lit); } } + +TEST_CASE("q2_light_low_luxel_res" * doctest::may_fail()) +{ + auto [bsp, bspx] = QbspVisLight_Q2( + "q2_light_low_luxel_res.map", {"-world_units_per_luxel", "32", "-dirt", "-debugface", "2164", "712", "-968"}); + + { + INFO("non-sloped cube"); + CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {254, 203, 0}, {2138, 712, -968}, {0, 1, 0}, nullptr, &bspx); + } + { + INFO("sloped cube"); + CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {254, 203, 0}, {2164, 712, -968}, {0, 1, 0}, nullptr, &bspx); + } +} \ No newline at end of file