diff --git a/qbsp/map.cc b/qbsp/map.cc index 8dc59d7b..e7dca7bb 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -536,7 +536,7 @@ int FindMiptex(const char *name, bool internal, bool recursive) return FindMiptex(name, extended_info, internal, recursive); } -static surfflags_t SurfFlagsForEntity(const maptexinfo_t &texinfo, const mapentity_t &entity) +static surfflags_t SurfFlagsForEntity(const maptexinfo_t &texinfo, const mapentity_t &entity, const contentflags_t &face_contents) { surfflags_t flags{}; const char *texname = map.miptex.at(texinfo.miptex).name.c_str(); @@ -600,6 +600,13 @@ static surfflags_t SurfFlagsForEntity(const maptexinfo_t &texinfo, const mapenti flags.no_shadow = true; } } + if (face_contents.is_liquid(qbsp_options.target_game)) { + // liquids (even opaque) don't cast shadow unless opted in + if (shadow != 1) { + flags.no_shadow = true; + } + } + // handle "_phong" and "_phong_angle" and "_phong_angle_concave" vec_t phongangle = entity.epairs.get_float("_phong_angle"); @@ -1816,7 +1823,7 @@ static std::optional ParseBrushFace(parser_t &parser, const mapbrush_ ValidateTextureProjection(face, &tx); - tx.flags = SurfFlagsForEntity(tx, entity); + tx.flags = SurfFlagsForEntity(tx, entity, face.contents); face.texinfo = FindTexinfo(tx); return face; diff --git a/testmaps/q2_dirt.map b/testmaps/q2_dirt.map new file mode 100644 index 00000000..dca0bba4 --- /dev/null +++ b/testmaps/q2_dirt.map @@ -0,0 +1,92 @@ +// Game: Quake 2 +// Format: Quake2 (Valve) +// entity 0 +{ +"mapversion" "220" +"classname" "worldspawn" +"_tb_textures" "textures/e1u1" +"_bounce" "0" +"_dirt" "1" +"_minlight" "0.75" +"_dirtscale" "2" +"_minlightMottle" "0" +"_tb_def" "builtin:Quake2.fgd" +// brush 0 +{ +( -160 -256 16 ) ( -160 -255 16 ) ( -160 -256 17 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 80 -384 16 ) ( 80 -384 17 ) ( 81 -384 16 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 80 -256 16 ) ( 81 -256 16 ) ( 80 -255 16 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 496 -32 32 ) ( 496 -31 32 ) ( 497 -32 32 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 496 368 32 ) ( 497 368 32 ) ( 496 368 33 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 496 -32 32 ) ( 496 -32 33 ) ( 496 -31 32 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 1 +{ +( 64 48 48 ) ( 64 49 48 ) ( 64 48 49 ) e1u1/brlava [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 8 8 0 +( 48 80 48 ) ( 48 80 49 ) ( 49 80 48 ) e1u1/brlava [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 8 8 0 +( 48 48 48 ) ( 49 48 48 ) ( 48 49 48 ) e1u1/brlava [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 8 8 0 +( 144 176 128 ) ( 144 177 128 ) ( 145 176 128 ) e1u1/brlava [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 8 8 0 +( 144 160 64 ) ( 145 160 64 ) ( 144 160 65 ) e1u1/brlava [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 8 8 0 +( 128 176 64 ) ( 128 176 65 ) ( 128 177 64 ) e1u1/brlava [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 8 8 0 +} +// brush 2 +{ +( -160 -384 32 ) ( -160 -383 32 ) ( -160 -384 33 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -160 -384 32 ) ( -160 -384 33 ) ( -159 -384 32 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -160 -384 32 ) ( -159 -384 32 ) ( -160 -383 32 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 256 -320 288 ) ( 256 -319 288 ) ( 257 -320 288 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 256 -320 48 ) ( 257 -320 48 ) ( 256 -320 49 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 496 -320 48 ) ( 496 -320 49 ) ( 496 -319 48 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 3 +{ +( -160 304 32 ) ( -160 305 32 ) ( -160 304 33 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -160 304 32 ) ( -160 304 33 ) ( -159 304 32 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -160 304 32 ) ( -159 304 32 ) ( -160 305 32 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 256 368 288 ) ( 256 369 288 ) ( 257 368 288 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 256 368 48 ) ( 257 368 48 ) ( 256 368 49 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 496 368 48 ) ( 496 368 49 ) ( 496 369 48 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 4 +{ +( -160 240 32 ) ( -160 241 32 ) ( -160 240 33 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -784 -320 32 ) ( -784 -320 33 ) ( -783 -320 32 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -784 240 32 ) ( -783 240 32 ) ( -784 241 32 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -368 304 288 ) ( -368 305 288 ) ( -367 304 288 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( -368 304 48 ) ( -367 304 48 ) ( -368 304 49 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -128 304 48 ) ( -128 304 49 ) ( -128 305 48 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 5 +{ +( -160 -256 288 ) ( -160 -255 288 ) ( -160 -256 289 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 80 -320 288 ) ( 80 -320 289 ) ( 81 -320 288 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 80 -256 288 ) ( 81 -256 288 ) ( 80 -255 288 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 496 -32 304 ) ( 496 -31 304 ) ( 497 -32 304 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 496 304 304 ) ( 497 304 304 ) ( 496 304 305 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 496 -32 304 ) ( 496 -32 305 ) ( 496 -31 304 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 6 +{ +( 496 240 32 ) ( 496 241 32 ) ( 496 240 33 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -128 -320 32 ) ( -128 -320 33 ) ( -127 -320 32 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( -128 240 32 ) ( -127 240 32 ) ( -128 241 32 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 288 304 288 ) ( 288 305 288 ) ( 289 304 288 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 288 304 48 ) ( 289 304 48 ) ( 288 304 49 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 528 304 48 ) ( 528 304 49 ) ( 528 305 48 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +} +// brush 7 +{ +( 16 -160 32 ) ( 16 -159 32 ) ( 16 -160 33 ) e1u1/floor1_1 [ 0 -1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 96 -176 32 ) ( 96 -176 33 ) ( 97 -176 32 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 96 -160 32 ) ( 97 -160 32 ) ( 96 -159 32 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 320 0 48 ) ( 320 1 48 ) ( 321 0 48 ) e1u1/floor1_1 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 +( 320 160 48 ) ( 321 160 48 ) ( 320 160 49 ) e1u1/floor1_1 [ -1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 +( 336 0 48 ) ( 336 0 49 ) ( 336 1 48 ) e1u1/floor1_1 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 +} +} +// entity 1 +{ +"classname" "info_player_start" +"origin" "192 -128 96" +"angle" "90" +} diff --git a/tests/test_ltface.cc b/tests/test_ltface.cc index 32daaac1..8ebb0304 100644 --- a/tests/test_ltface.cc +++ b/tests/test_ltface.cc @@ -209,3 +209,16 @@ TEST_CASE("q2_minlight_nomottle") { CHECK(sample == qvec3b(33, 33, 33)); }); } + +TEST_CASE("q2_dirt") { + INFO("liquids don't cast dirt"); + + auto [bsp, bspx] = LoadTestmap("q2_dirt.map", {}); + + auto *face_under_lava = BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], {104, 112, 48}); + REQUIRE(face_under_lava); + + CheckFaceLuxels(bsp, *face_under_lava, [](qvec3b sample){ + CHECK(sample == qvec3b(96)); + }); +}