diff --git a/common/bsputils.cc b/common/bsputils.cc index 1429a7b2..4a7c2a18 100644 --- a/common/bsputils.cc +++ b/common/bsputils.cc @@ -1015,10 +1015,15 @@ qvec3f faceextents_t::LMCoordToWorld(qvec2f lm) const /** * Samples the lightmap at an integer coordinate + * FIXME: this doesn't deal with styles at all */ qvec3b LM_Sample(const mbsp_t *bsp, const std::vector *lit, const faceextents_t &faceextents, int byte_offset_of_face, qvec2i coord) { + if (byte_offset_of_face == -1) { + return {0, 0, 0}; + } + Q_assert(coord[0] >= 0); Q_assert(coord[1] >= 0); Q_assert(coord[0] < faceextents.width()); diff --git a/testmaps/q1_lightignore.map b/testmaps/q1_lightignore.map new file mode 100644 index 00000000..5be2d41d --- /dev/null +++ b/testmaps/q1_lightignore.map @@ -0,0 +1,100 @@ +// Game: Quake +// Format: Standard +// entity 0 +{ +"classname" "worldspawn" +"wad" "deprecated/free_wad.wad" +// brush 0 +{ +( -304 32 16 ) ( -304 256 16 ) ( -304 32 192 ) bolt9 0 0 0 1 1 +( -304 32 192 ) ( -288 32 192 ) ( -304 32 16 ) bolt9 0 0 0 1 1 +( -304 32 16 ) ( -288 32 16 ) ( -304 256 16 ) bolt9 0 0 0 1 1 +( -304 256 192 ) ( -288 256 192 ) ( -304 32 192 ) bolt9 0 0 0 1 1 +( -304 256 16 ) ( -288 256 16 ) ( -304 256 192 ) bolt9 0 0 0 1 1 +( -288 32 16 ) ( -288 32 192 ) ( -288 256 16 ) bolt9 0 0 0 1 1 +} +// brush 1 +{ +( -288 256 192 ) ( -288 240 192 ) ( -288 256 16 ) bolt9 0 0 0 1 1 +( -64 240 192 ) ( -64 240 16 ) ( -288 240 192 ) bolt9 0 0 0 1 1 +( -288 256 16 ) ( -288 240 16 ) ( -64 256 16 ) bolt9 0 0 0 1 1 +( -64 256 192 ) ( -64 240 192 ) ( -288 256 192 ) bolt9 0 0 0 1 1 +( -64 256 192 ) ( -288 256 192 ) ( -64 256 16 ) bolt9 0 0 0 1 1 +( 224 256 16 ) ( 224 240 16 ) ( 224 256 192 ) bolt9 0 0 0 1 1 +} +// brush 2 +{ +( -288 32 16 ) ( -288 48 16 ) ( -288 32 192 ) bolt9 0 0 0 1 1 +( -64 32 16 ) ( -288 32 16 ) ( -64 32 192 ) bolt9 0 0 0 1 1 +( -64 32 16 ) ( -64 48 16 ) ( -288 32 16 ) bolt9 0 0 0 1 1 +( -288 32 192 ) ( -288 48 192 ) ( -64 32 192 ) bolt9 0 0 0 1 1 +( -288 48 16 ) ( -64 48 16 ) ( -288 48 192 ) bolt9 0 0 0 1 1 +( 224 32 192 ) ( 224 48 192 ) ( 224 32 16 ) bolt9 0 0 0 1 1 +} +// brush 3 +{ +( -288 48 192 ) ( -288 48 176 ) ( -288 240 192 ) bolt9 0 0 0 1 1 +( -64 48 192 ) ( -64 48 176 ) ( -288 48 192 ) bolt9 0 0 0 1 1 +( -64 240 176 ) ( -288 240 176 ) ( -64 48 176 ) bolt9 0 0 0 1 1 +( -64 240 192 ) ( -64 48 192 ) ( -288 240 192 ) bolt9 0 0 0 1 1 +( -288 240 192 ) ( -288 240 176 ) ( -64 240 192 ) bolt9 0 0 0 1 1 +( 224 240 192 ) ( 224 240 176 ) ( 224 48 192 ) bolt9 0 0 0 1 1 +} +// brush 4 +{ +( -288 240 16 ) ( -288 240 32 ) ( -288 48 16 ) bolt9 0 0 0 1 1 +( -288 48 16 ) ( -288 48 32 ) ( -64 48 16 ) bolt9 0 0 0 1 1 +( -288 240 16 ) ( -288 48 16 ) ( -64 240 16 ) bolt9 0 0 0 1 1 +( -288 48 32 ) ( -288 240 32 ) ( -64 48 32 ) bolt9 0 0 0 1 1 +( -64 240 16 ) ( -64 240 32 ) ( -288 240 16 ) bolt9 0 0 0 1 1 +( 224 48 16 ) ( 224 48 32 ) ( 224 240 16 ) bolt9 0 0 0 1 1 +} +// brush 5 +{ +( 208 48 32 ) ( 208 49 32 ) ( 208 48 33 ) bolt9 0 0 0 1 1 +( 208 48 32 ) ( 208 48 33 ) ( 209 48 32 ) bolt9 0 0 0 1 1 +( 208 48 32 ) ( 209 48 32 ) ( 208 49 32 ) bolt9 0 0 0 1 1 +( 224 240 192 ) ( 224 241 192 ) ( 225 240 192 ) bolt9 0 0 0 1 1 +( 224 240 40 ) ( 225 240 40 ) ( 224 240 41 ) bolt9 0 0 0 1 1 +( 224 240 40 ) ( 224 240 41 ) ( 224 241 40 ) bolt9 0 0 0 1 1 +} +} +// entity 1 +{ +"classname" "info_player_start" +"origin" "-192 132 56" +} +// entity 2 +{ +"classname" "light" +"origin" "-24 152 120" +"_color" "0.4 0.5 0.6" +} +// entity 3 +{ +"classname" "func_detail" +"_lightignore" "1" +// brush 0 +{ +( 32 112 32 ) ( 32 113 32 ) ( 32 112 33 ) bolt9 32 0 0 1 1 +( 32 112 32 ) ( 32 112 33 ) ( 33 112 32 ) bolt9 16 0 0 1 1 +( 32 112 32 ) ( 33 112 32 ) ( 32 113 32 ) bolt9 16 -32 0 1 1 +( 112 176 48 ) ( 112 177 48 ) ( 113 176 48 ) bolt9 16 -32 0 1 1 +( 112 176 48 ) ( 113 176 48 ) ( 112 176 49 ) bolt9 16 0 0 1 1 +( 112 176 48 ) ( 112 176 49 ) ( 112 177 48 ) bolt9 32 0 0 1 1 +} +} +// entity 4 +{ +"classname" "func_wall" +"_lightignore" "1" +// brush 0 +{ +( -80 112 32 ) ( -80 113 32 ) ( -80 112 33 ) bolt9 32 0 0 1 1 +( -80 112 32 ) ( -80 112 33 ) ( -79 112 32 ) bolt9 0 0 0 1 1 +( -80 112 32 ) ( -79 112 32 ) ( -80 113 32 ) bolt9 0 -32 0 1 1 +( 0 176 48 ) ( 0 177 48 ) ( 1 176 48 ) bolt9 0 -32 0 1 1 +( 0 176 48 ) ( 1 176 48 ) ( 0 176 49 ) bolt9 0 0 0 1 1 +( 0 176 48 ) ( 0 176 49 ) ( 0 177 48 ) bolt9 32 0 0 1 1 +} +} diff --git a/tests/test_ltface.cc b/tests/test_ltface.cc index c0124153..814fe275 100644 --- a/tests/test_ltface.cc +++ b/tests/test_ltface.cc @@ -240,7 +240,7 @@ 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 qvec3d &point, const qvec3d &normal = {0, 0, 0}, const std::vector *lit = nullptr) { auto *face = BSP_FindFaceAtPoint(bsp, model, point, normal); REQUIRE(face); @@ -251,7 +251,7 @@ static void CheckFaceLuxelAtPoint(const mbsp_t *bsp, const dmodelh2_t *model, co const auto coord = extents.worldToLMCoord(point); - const qvec3b sample = LM_Sample(bsp, nullptr, extents, face->lightofs, qvec2i(coord)); + const qvec3b sample = LM_Sample(bsp, lit, extents, face->lightofs, qvec2i(coord)); INFO("sample ", coord[0], ", ", coord[1]); CHECK(sample == expected_color); @@ -624,3 +624,21 @@ TEST_CASE("q2_surface_lights_culling") CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {155, 78, 39}, {-480, 168, 64}); } + +TEST_CASE("q1_lightignore") +{ + auto [bsp, bspx, lit] = QbspVisLight_Q1("q1_lightignore.map", {"-bounce"}); + + { + INFO("func_wall"); + CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[1], {0, 0, 0}, {-48, 144, 48}, {0, 0, 1}, &lit); + } + { + INFO("func_detail"); + CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {0, 0, 0}, {72, 144, 48}, {0, 0, 1}, &lit); + } + { + INFO("worldspawn (receives light)"); + CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {55, 69, 83}, {-128, 144, 32}, {0, 0, 1}, &lit); + } +}