qbsp, light: fix inheriting minlight from worldspawn

Update q2_light_group.map to support this
This commit is contained in:
Eric Wasylishen 2023-05-07 20:49:58 -06:00
parent f9ad83aed5
commit 3e446e6ea6
7 changed files with 127 additions and 11 deletions

View File

@ -176,7 +176,8 @@ struct surfflags_t
// light doesn't bounce off this face
bool no_bounce;
// opt out of minlight on this face
// opt out of minlight on this face (including opting out of local minlight, so
// not the same as just setting minlight to 0).
bool no_minlight;
// don't expand this face for larger clip hulls
@ -210,8 +211,8 @@ struct surfflags_t
// _phong_group key, equivalent q2 map format's use of the "value" field
int phong_group;
// minlight value for this face
vec_t minlight;
// minlight value for this face. empty = inherit from worldspawn.
std::optional<vec_t> minlight;
// red minlight colors for this face
qvec3b minlight_color;

View File

@ -615,8 +615,10 @@ static std::unique_ptr<lightsurf_t> Lightsurf_Init(const modelinfo_t *modelinfo,
// minlight
if (modelinfo->minlight.is_changed()) {
lightsurf->minlight = modelinfo->minlight.value();
} else if (extended_flags.minlight) {
lightsurf->minlight = *extended_flags.minlight;
} else {
lightsurf->minlight = extended_flags.minlight;
lightsurf->minlight = light_options.minlight.value();
}
// minlightMottle

View File

@ -740,11 +740,10 @@ static surfflags_t SurfFlagsForEntity(
flags.phong_group = entity.epairs.get_int("_phong_group");
// handle "_minlight"
const vec_t minlight = entity.epairs.get_float("_minlight");
if (minlight > 0) {
// CHECK: allow > 510 now that we're float? or is it not worth it since it will
// be beyond max?
flags.minlight = clamp(minlight, 0.0, 510.0);
if (entity.epairs.has("_minlight")) {
const vec_t minlight = entity.epairs.get_float("_minlight");
// handle -1 as an alias for 0 (same with other negative values).
flags.minlight = max(0., minlight);
}
// handle "_maxlight"

View File

@ -403,7 +403,7 @@ static void WriteExtendedTexinfoFlags(void)
t["phong_group"] = tx.flags.phong_group;
}
if (tx.flags.minlight) {
t["minlight"] = tx.flags.minlight;
t["minlight"] = *tx.flags.minlight;
}
if (tx.flags.maxlight) {
t["maxlight"] = tx.flags.maxlight;

View File

@ -145,6 +145,7 @@
{
"classname" "func_wall"
"_object_channel_mask" "2"
"_minlight" "0"
// brush 0
{
( 656 1280 944 ) ( 656 1281 944 ) ( 656 1280 945 ) e1u1/twall2_1 -32 0 0 1 1
@ -177,6 +178,7 @@
{
"classname" "func_wall"
"_object_channel_mask" "4"
"_minlight" "0"
// brush 0
{
( 880 1248 944 ) ( 880 1249 944 ) ( 880 1248 945 ) e1u1/twall2_1 0 0 0 1 1
@ -208,6 +210,7 @@
"classname" "func_wall"
"_object_channel_mask" "8"
"_shadow" "1"
"_minlight" "0"
// brush 0
{
( 1264 1248 944 ) ( 1264 1249 944 ) ( 1264 1248 945 ) e1u1/twall2_1 0 0 0 1 1
@ -230,6 +233,7 @@
{
"classname" "func_group"
"_object_channel_mask" "8"
"_minlight" "0"
// brush 0
{
( 1456 1248 944 ) ( 1456 1249 944 ) ( 1456 1248 945 ) e1u1/twall2_1 0 0 0 1 1

View File

@ -0,0 +1,96 @@
// Game: Quake 2
// Format: Quake2
// entity 0
{
"classname" "worldspawn"
"_tb_textures" "textures/e1u1"
"_bounce" "0"
"_minlight" "0.5"
"_minlight_mottle" "0"
// brush 0
{
( -480 -176 -16 ) ( -480 -175 -16 ) ( -480 -176 -15 ) e1u1/twall2_1 -16 112 0 1 1
( -256 -176 -16 ) ( -256 -176 -15 ) ( -255 -176 -16 ) e1u1/twall2_1 64 112 0 1 1
( -256 -176 -16 ) ( -255 -176 -16 ) ( -256 -175 -16 ) e1u1/twall2_1 64 16 0 1 1
( -16 208 0 ) ( -16 209 0 ) ( -15 208 0 ) e1u1/twall2_1 64 16 0 1 1
( -16 224 0 ) ( -15 224 0 ) ( -16 224 1 ) e1u1/twall2_1 64 112 0 1 1
( 480 208 0 ) ( 480 208 1 ) ( 480 209 0 ) e1u1/twall2_1 -16 112 0 1 1
}
// brush 1
{
( -480 -176 304 ) ( -480 -175 304 ) ( -480 -176 305 ) e1u1/twall2_1 64 16 0 1 1
( -256 -192 304 ) ( -256 -192 305 ) ( -255 -192 304 ) e1u1/twall2_1 64 16 0 1 1
( -256 -176 304 ) ( -255 -176 304 ) ( -256 -175 304 ) e1u1/twall2_1 64 16 0 1 1
( -16 208 320 ) ( -16 209 320 ) ( -15 208 320 ) e1u1/twall2_1 64 16 0 1 1
( -16 224 320 ) ( -15 224 320 ) ( -16 224 321 ) e1u1/twall2_1 64 16 0 1 1
( 480 208 320 ) ( 480 208 321 ) ( 480 209 320 ) e1u1/twall2_1 64 16 0 1 1
}
// brush 2
{
( -480 -192 -16 ) ( -480 -191 -16 ) ( -480 -192 -15 ) e1u1/twall2_1 64 16 0 1 1
( -256 -192 -16 ) ( -256 -192 -15 ) ( -255 -192 -16 ) e1u1/twall2_1 64 16 0 1 1
( -256 -192 -16 ) ( -255 -192 -16 ) ( -256 -191 -16 ) e1u1/twall2_1 64 16 0 1 1
( -16 192 304 ) ( -16 193 304 ) ( -15 192 304 ) e1u1/twall2_1 64 16 0 1 1
( -16 -176 0 ) ( -15 -176 0 ) ( -16 -176 1 ) e1u1/twall2_1 64 16 0 1 1
( 496 192 0 ) ( 496 192 1 ) ( 496 193 0 ) e1u1/twall2_1 64 16 0 1 1
}
// brush 3
{
( -480 128 -16 ) ( -480 129 -16 ) ( -480 128 -15 ) e1u1/twall2_1 64 16 0 1 1
( -128 224 -16 ) ( -128 224 -15 ) ( -127 224 -16 ) e1u1/twall2_1 64 16 0 1 1
( -128 128 -16 ) ( -127 128 -16 ) ( -128 129 -16 ) e1u1/twall2_1 64 16 0 1 1
( 112 512 304 ) ( 112 513 304 ) ( 113 512 304 ) e1u1/twall2_1 64 16 0 1 1
( 112 240 0 ) ( 113 240 0 ) ( 112 240 1 ) e1u1/twall2_1 64 16 0 1 1
( 480 128 -16 ) ( 480 128 -15 ) ( 480 129 -16 ) e1u1/twall2_1 64 16 0 1 1
}
// brush 4
{
( 480 -176 112 ) ( 480 -175 112 ) ( 480 -176 113 ) e1u1/twall2_1 64 16 0 1 1
( 160 -176 112 ) ( 160 -176 113 ) ( 161 -176 112 ) e1u1/twall2_1 64 16 0 1 1
( 160 -176 -16 ) ( 161 -176 -16 ) ( 160 -175 -16 ) e1u1/twall2_1 64 16 0 1 1
( 400 208 304 ) ( 400 209 304 ) ( 401 208 304 ) e1u1/twall2_1 64 16 0 1 1
( 400 224 128 ) ( 401 224 128 ) ( 400 224 129 ) e1u1/twall2_1 64 16 0 1 1
( 496 208 128 ) ( 496 208 129 ) ( 496 209 128 ) e1u1/twall2_1 64 16 0 1 1
}
// brush 5
{
( -496 -176 112 ) ( -496 -175 112 ) ( -496 -176 113 ) e1u1/twall2_1 64 16 0 1 1
( -816 -192 112 ) ( -816 -192 113 ) ( -815 -192 112 ) e1u1/twall2_1 64 16 0 1 1
( -816 -176 -16 ) ( -815 -176 -16 ) ( -816 -175 -16 ) e1u1/twall2_1 64 16 0 1 1
( -576 208 304 ) ( -576 209 304 ) ( -575 208 304 ) e1u1/twall2_1 64 16 0 1 1
( -576 224 128 ) ( -575 224 128 ) ( -576 224 129 ) e1u1/twall2_1 64 16 0 1 1
( -480 208 128 ) ( -480 208 129 ) ( -480 209 128 ) e1u1/twall2_1 64 16 0 1 1
}
}
// entity 1
{
"classname" "info_player_start"
"origin" "272 -104 24"
"angle" "90"
}
// entity 2
{
"classname" "func_group"
// brush 0
{
( 288 0 0 ) ( 288 1 0 ) ( 288 0 1 ) e1u1/twall2_1 -16 16 0 1 1
( 176 0 0 ) ( 176 0 1 ) ( 177 0 0 ) e1u1/twall2_1 0 16 0 1 1
( 176 0 0 ) ( 177 0 0 ) ( 176 1 0 ) e1u1/twall2_1 0 -32 0 1 1
( 416 144 16 ) ( 416 145 16 ) ( 417 144 16 ) e1u1/twall2_1 0 -32 0 1 1
( 416 144 16 ) ( 417 144 16 ) ( 416 144 17 ) e1u1/twall2_1 0 16 0 1 1
( 416 144 16 ) ( 416 144 17 ) ( 416 145 16 ) e1u1/twall2_1 -16 16 0 1 1
}
}
// entity 3
{
"classname" "func_wall"
// brush 0
{
( 144 0 0 ) ( 144 1 0 ) ( 144 0 1 ) e1u1/twall2_1 -16 16 0 1 1
( 32 0 0 ) ( 32 0 1 ) ( 33 0 0 ) e1u1/twall2_1 16 16 0 1 1
( 32 0 0 ) ( 33 0 0 ) ( 32 1 0 ) e1u1/twall2_1 16 -32 0 1 1
( 272 144 16 ) ( 272 145 16 ) ( 273 144 16 ) e1u1/twall2_1 16 -32 0 1 1
( 272 144 16 ) ( 273 144 16 ) ( 272 144 17 ) e1u1/twall2_1 16 16 0 1 1
( 272 144 16 ) ( 272 144 17 ) ( 272 145 16 ) e1u1/twall2_1 -16 16 0 1 1
}
}

View File

@ -681,4 +681,18 @@ TEST_CASE("q2_light_low_luxel_res2" * doctest::may_fail())
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {49, 49, 49}, {2964, 1046, -694}, {-1, 0, 0}, nullptr, &bspx);
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {25, 25, 25}, {2964, 1046, -706}, {-1, 0, 0}, nullptr, &bspx);
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {1, 1, 1}, {2964, 1046, -716}, {-1, 0, 0}, nullptr, &bspx);
}
}
TEST_CASE("q2_minlight_inherited")
{
auto [bsp, bspx] = QbspVisLight_Q2("q2_minlight_inherited.map", {});
{
INFO("check that func_group inherits worldspawn minlight");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {64, 64, 64}, {360, 72, 16}, {0, 0, 1}, nullptr, &bspx);
}
{
INFO("check that func_wall inherits worldspawn minlight");
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[1], {64, 64, 64}, {208, 72, 16}, {0, 0, 1}, nullptr, &bspx);
}
}