light: add _switchableshadow_target
Switchable shadows setup which works in id1 Fixes #432
This commit is contained in:
parent
8ac82b7c79
commit
e5f01ce0e3
|
|
@ -1099,10 +1099,10 @@ static int StyleOffset(int style, const mface_t *face, const faceextents_t &face
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Samples the lightmap at an integer coordinate in style 0
|
* Samples the lightmap at an integer coordinate in the given style
|
||||||
*/
|
*/
|
||||||
qvec3b LM_Sample(const mbsp_t *bsp, const mface_t *face, const lit_variant_t *lit, const faceextents_t &faceextents,
|
qvec3b LM_Sample(const mbsp_t *bsp, const mface_t *face, const lit_variant_t *lit, const faceextents_t &faceextents,
|
||||||
int byte_offset_of_face, qvec2i coord)
|
int byte_offset_of_face, qvec2i coord, int style)
|
||||||
{
|
{
|
||||||
if (byte_offset_of_face == -1) {
|
if (byte_offset_of_face == -1) {
|
||||||
return {0, 0, 0};
|
return {0, 0, 0};
|
||||||
|
|
@ -1113,7 +1113,7 @@ qvec3b LM_Sample(const mbsp_t *bsp, const mface_t *face, const lit_variant_t *li
|
||||||
Q_assert(coord[0] < faceextents.width());
|
Q_assert(coord[0] < faceextents.width());
|
||||||
Q_assert(coord[1] < faceextents.height());
|
Q_assert(coord[1] < faceextents.height());
|
||||||
|
|
||||||
int style_offset = StyleOffset(0, face, faceextents);
|
int style_offset = StyleOffset(style, face, faceextents);
|
||||||
if (style_offset == -1) {
|
if (style_offset == -1) {
|
||||||
return {0, 0, 0};
|
return {0, 0, 0};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -665,6 +665,11 @@ If used on func_detail* or func_group, a full qbsp pass need to be run.
|
||||||
through the switchable shadow casters, regardless of whether the shadow
|
through the switchable shadow casters, regardless of whether the shadow
|
||||||
is off or on.
|
is off or on.
|
||||||
|
|
||||||
|
.. seealso::
|
||||||
|
|
||||||
|
The light entity key :light-key:`_switchableshadow_target` allows using switchable
|
||||||
|
shadows in ID1 Quake, without custom QC, although the setup is more awkward.
|
||||||
|
|
||||||
.. bmodel-key:: "_dirt" "n"
|
.. bmodel-key:: "_dirt" "n"
|
||||||
|
|
||||||
For brush models, -1 prevents dirtmapping on the brush model. Useful
|
For brush models, -1 prevents dirtmapping on the brush model. Useful
|
||||||
|
|
@ -918,6 +923,21 @@ Point Lights
|
||||||
Set to 1 to make the light compiler ignore this entity (prevents it
|
Set to 1 to make the light compiler ignore this entity (prevents it
|
||||||
from casting any light). e.g. could be useful with rtlights.
|
from casting any light). e.g. could be useful with rtlights.
|
||||||
|
|
||||||
|
.. light-key:: "_switchableshadow_target" "name"
|
||||||
|
|
||||||
|
Calculate lighting with and without bmodels with a "targetname" equal to "name",
|
||||||
|
and stores the resulting switchable shadow data in a light style which is stored in this light
|
||||||
|
entity's "style" key.
|
||||||
|
|
||||||
|
You should give this light a :light-key:`targetname` and typically set "spawnflags" "1" (start off).
|
||||||
|
|
||||||
|
Implies :light-key:`_nostaticlight` (this entity itself does not cast any light).
|
||||||
|
|
||||||
|
.. hint::
|
||||||
|
|
||||||
|
If your mod supports it, you should prefer to use bmodel key :bmodel-key:`_switchableshadow`
|
||||||
|
to enable switchable shadows.
|
||||||
|
|
||||||
Spotlights
|
Spotlights
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -176,7 +176,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
qvec3b LM_Sample(const mbsp_t *bsp, const mface_t *face, const lit_variant_t *lit, const faceextents_t &faceextents,
|
qvec3b LM_Sample(const mbsp_t *bsp, const mface_t *face, const lit_variant_t *lit, const faceextents_t &faceextents,
|
||||||
int byte_offset_of_face, qvec2i coord);
|
int byte_offset_of_face, qvec2i coord, int style = 0);
|
||||||
|
|
||||||
qvec3f LM_Sample_HDR(const mbsp_t *bsp,
|
qvec3f LM_Sample_HDR(const mbsp_t *bsp,
|
||||||
const mface_t *face,
|
const mface_t *face,
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,7 @@ public:
|
||||||
settings::setting_int32 light_channel_mask;
|
settings::setting_int32 light_channel_mask;
|
||||||
settings::setting_int32 shadow_channel_mask;
|
settings::setting_int32 shadow_channel_mask;
|
||||||
settings::setting_bool nonudge;
|
settings::setting_bool nonudge;
|
||||||
|
settings::setting_string switchableshadow_target;
|
||||||
|
|
||||||
light_t();
|
light_t();
|
||||||
|
|
||||||
|
|
@ -143,6 +144,10 @@ std::vector<std::unique_ptr<light_t>> &GetLights();
|
||||||
const std::vector<entdict_t> &GetEntdicts();
|
const std::vector<entdict_t> &GetEntdicts();
|
||||||
std::vector<sun_t> &GetSuns();
|
std::vector<sun_t> &GetSuns();
|
||||||
std::vector<entdict_t> &GetRadLights();
|
std::vector<entdict_t> &GetRadLights();
|
||||||
|
/**
|
||||||
|
* Returns the light entity that has "_switchableshadow_target" set to the given value, or nullptr.
|
||||||
|
*/
|
||||||
|
light_t *LightWithSwitchableShadowTargetValue(const std::string &target);
|
||||||
|
|
||||||
const std::vector<std::unique_ptr<light_t>> &GetSurfaceLightTemplates();
|
const std::vector<std::unique_ptr<light_t>> &GetSurfaceLightTemplates();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ static std::vector<std::pair<std::string, int>> lightstyleForTargetname;
|
||||||
static std::vector<std::unique_ptr<light_t>> surfacelight_templates;
|
static std::vector<std::unique_ptr<light_t>> surfacelight_templates;
|
||||||
static std::ofstream surflights_dump_file;
|
static std::ofstream surflights_dump_file;
|
||||||
static fs::path surflights_dump_filename;
|
static fs::path surflights_dump_filename;
|
||||||
|
static std::map<std::string, light_t*> lights_by_switchableshadow_target;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets global data in this file
|
* Resets global data in this file
|
||||||
|
|
@ -58,6 +59,7 @@ void ResetLightEntities()
|
||||||
surfacelight_templates.clear();
|
surfacelight_templates.clear();
|
||||||
surflights_dump_file = {};
|
surflights_dump_file = {};
|
||||||
surflights_dump_filename.clear();
|
surflights_dump_filename.clear();
|
||||||
|
lights_by_switchableshadow_target.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<light_t>> &GetLights()
|
std::vector<std::unique_ptr<light_t>> &GetLights()
|
||||||
|
|
@ -80,6 +82,16 @@ std::vector<entdict_t> &GetRadLights()
|
||||||
return radlights;
|
return radlights;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
light_t *LightWithSwitchableShadowTargetValue(const std::string &target)
|
||||||
|
{
|
||||||
|
auto it = lights_by_switchableshadow_target.find(target);
|
||||||
|
|
||||||
|
if (it == lights_by_switchableshadow_target.end())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
/* surface lights */
|
/* surface lights */
|
||||||
static void MakeSurfaceLights(const mbsp_t *bsp);
|
static void MakeSurfaceLights(const mbsp_t *bsp);
|
||||||
|
|
||||||
|
|
@ -121,7 +133,8 @@ light_t::light_t()
|
||||||
surflight_atten{this, "surflight_atten", 1.f},
|
surflight_atten{this, "surflight_atten", 1.f},
|
||||||
light_channel_mask{this, "light_channel_mask", CHANNEL_MASK_DEFAULT},
|
light_channel_mask{this, "light_channel_mask", CHANNEL_MASK_DEFAULT},
|
||||||
shadow_channel_mask{this, "shadow_channel_mask", CHANNEL_MASK_DEFAULT},
|
shadow_channel_mask{this, "shadow_channel_mask", CHANNEL_MASK_DEFAULT},
|
||||||
nonudge{this, "nonudge", false}
|
nonudge{this, "nonudge", false},
|
||||||
|
switchableshadow_target{this, "switchableshadow_target", ""}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1062,6 +1075,14 @@ void LoadEntities(const settings::worldspawn_keys &cfg, const mbsp_t *bsp)
|
||||||
entity->projfov.value(), entity->projectionmatrix);
|
entity->projfov.value(), entity->projectionmatrix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vanilla-compatible switchable shadows
|
||||||
|
const std::string &switchableshadow_target = entity->switchableshadow_target.value();
|
||||||
|
if (!switchableshadow_target.empty()) {
|
||||||
|
entity->nostaticlight.set_value(true, settings::source::DEFAULT);
|
||||||
|
|
||||||
|
lights_by_switchableshadow_target[switchableshadow_target] = entity.get();
|
||||||
|
}
|
||||||
|
|
||||||
CheckEntityFields(bsp, cfg, entity.get());
|
CheckEntityFields(bsp, cfg, entity.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -725,6 +725,13 @@ static void FindModelInfo(const mbsp_t *bsp)
|
||||||
// apply settings
|
// apply settings
|
||||||
info->set_settings(*entdict, settings::source::MAP);
|
info->set_settings(*entdict, settings::source::MAP);
|
||||||
|
|
||||||
|
// vanilla-compatible switchable shadows
|
||||||
|
if (auto *light = LightWithSwitchableShadowTargetValue(entdict->get("targetname"))) {
|
||||||
|
// take the "style" key from this light entity and enable switchable shadows on ourself
|
||||||
|
info->switchableshadow.set_value(true, settings::source::DEFAULT);
|
||||||
|
info->switchshadstyle.set_value(light->style.value(), settings::source::DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if this model will cast shadows (shadow => shadowself) */
|
/* Check if this model will cast shadows (shadow => shadowself) */
|
||||||
if (info->switchableshadow.boolValue()) {
|
if (info->switchableshadow.boolValue()) {
|
||||||
Q_assert(info->switchshadstyle.value() != 0);
|
Q_assert(info->switchshadstyle.value() != 0);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,184 @@
|
||||||
|
// Game: Quake
|
||||||
|
// Format: Standard
|
||||||
|
// entity 0
|
||||||
|
{
|
||||||
|
"classname" "worldspawn"
|
||||||
|
"_tb_textures" "textures/e1u1"
|
||||||
|
"wad" "deprecated/free_wad.wad"
|
||||||
|
// brush 0
|
||||||
|
{
|
||||||
|
( 480 1088 928 ) ( 480 1089 928 ) ( 480 1088 929 ) bolt14 0 32 0 1 1
|
||||||
|
( 704 1088 928 ) ( 704 1088 929 ) ( 705 1088 928 ) bolt14 0 32 0 1 1
|
||||||
|
( 704 1088 928 ) ( 705 1088 928 ) ( 704 1089 928 ) bolt14 0 0 0 1 1
|
||||||
|
( 944 1472 944 ) ( 944 1473 944 ) ( 945 1472 944 ) bolt14 0 0 0 1 1
|
||||||
|
( 944 1488 944 ) ( 945 1488 944 ) ( 944 1488 945 ) bolt14 0 32 0 1 1
|
||||||
|
( 1056 1472 944 ) ( 1056 1472 945 ) ( 1056 1473 944 ) bolt14 0 32 0 1 1
|
||||||
|
}
|
||||||
|
// brush 1
|
||||||
|
{
|
||||||
|
( 480 1088 1248 ) ( 480 1089 1248 ) ( 480 1088 1249 ) bolt14 0 96 0 1 1
|
||||||
|
( 704 1072 1248 ) ( 704 1072 1249 ) ( 705 1072 1248 ) bolt14 0 96 0 1 1
|
||||||
|
( 704 1088 1248 ) ( 705 1088 1248 ) ( 704 1089 1248 ) bolt14 0 0 0 1 1
|
||||||
|
( 944 1472 1264 ) ( 944 1473 1264 ) ( 945 1472 1264 ) bolt14 0 0 0 1 1
|
||||||
|
( 944 1488 1264 ) ( 945 1488 1264 ) ( 944 1488 1265 ) bolt14 0 96 0 1 1
|
||||||
|
( 1056 1472 1264 ) ( 1056 1472 1265 ) ( 1056 1473 1264 ) bolt14 0 96 0 1 1
|
||||||
|
}
|
||||||
|
// brush 2
|
||||||
|
{
|
||||||
|
( 480 1072 928 ) ( 480 1073 928 ) ( 480 1072 929 ) bolt14 16 32 0 1 1
|
||||||
|
( 704 1072 928 ) ( 704 1072 929 ) ( 705 1072 928 ) bolt14 0 32 0 1 1
|
||||||
|
( 704 1072 928 ) ( 705 1072 928 ) ( 704 1073 928 ) bolt14 0 -16 0 1 1
|
||||||
|
( 944 1456 1248 ) ( 944 1457 1248 ) ( 945 1456 1248 ) bolt14 0 -16 0 1 1
|
||||||
|
( 944 1088 944 ) ( 945 1088 944 ) ( 944 1088 945 ) bolt14 0 32 0 1 1
|
||||||
|
( 1056 1456 944 ) ( 1056 1456 945 ) ( 1056 1457 944 ) bolt14 16 32 0 1 1
|
||||||
|
}
|
||||||
|
// brush 3
|
||||||
|
{
|
||||||
|
( 480 1392 928 ) ( 480 1393 928 ) ( 480 1392 929 ) bolt14 -48 32 0 1 1
|
||||||
|
( 832 1488 928 ) ( 832 1488 929 ) ( 833 1488 928 ) bolt14 -128 32 0 1 1
|
||||||
|
( 832 1392 928 ) ( 833 1392 928 ) ( 832 1393 928 ) bolt14 -128 48 0 1 1
|
||||||
|
( 1072 1776 1248 ) ( 1072 1777 1248 ) ( 1073 1776 1248 ) bolt14 -128 48 0 1 1
|
||||||
|
( 1072 1504 944 ) ( 1073 1504 944 ) ( 1072 1504 945 ) bolt14 -128 32 0 1 1
|
||||||
|
( 1056 1392 928 ) ( 1056 1392 929 ) ( 1056 1393 928 ) bolt14 -48 32 0 1 1
|
||||||
|
}
|
||||||
|
// brush 4
|
||||||
|
{
|
||||||
|
( 1056 1088 1056 ) ( 1056 1089 1056 ) ( 1056 1088 1057 ) bolt14 0 32 0 1 1
|
||||||
|
( 736 1088 1056 ) ( 736 1088 1057 ) ( 737 1088 1056 ) bolt14 -32 32 0 1 1
|
||||||
|
( 736 1088 928 ) ( 737 1088 928 ) ( 736 1089 928 ) bolt14 -32 0 0 1 1
|
||||||
|
( 976 1472 1248 ) ( 976 1473 1248 ) ( 977 1472 1248 ) bolt14 -32 0 0 1 1
|
||||||
|
( 976 1488 1072 ) ( 977 1488 1072 ) ( 976 1488 1073 ) bolt14 -32 32 0 1 1
|
||||||
|
( 1072 1472 1072 ) ( 1072 1472 1073 ) ( 1072 1473 1072 ) bolt14 0 32 0 1 1
|
||||||
|
}
|
||||||
|
// brush 5
|
||||||
|
{
|
||||||
|
( 464 1088 1056 ) ( 464 1089 1056 ) ( 464 1088 1057 ) bolt14 0 32 0 1 1
|
||||||
|
( 144 1072 1056 ) ( 144 1072 1057 ) ( 145 1072 1056 ) bolt14 48 32 0 1 1
|
||||||
|
( 144 1088 928 ) ( 145 1088 928 ) ( 144 1089 928 ) bolt14 48 0 0 1 1
|
||||||
|
( 384 1472 1248 ) ( 384 1473 1248 ) ( 385 1472 1248 ) bolt14 48 0 0 1 1
|
||||||
|
( 384 1488 1072 ) ( 385 1488 1072 ) ( 384 1488 1073 ) bolt14 48 32 0 1 1
|
||||||
|
( 480 1472 1072 ) ( 480 1472 1073 ) ( 480 1473 1072 ) bolt14 0 32 0 1 1
|
||||||
|
}
|
||||||
|
// brush 6
|
||||||
|
{
|
||||||
|
( 704 1088 944 ) ( 704 1089 944 ) ( 704 1088 945 ) bolt10 0 0 0 1 1
|
||||||
|
( 704 1088 944 ) ( 704 1088 945 ) ( 705 1088 944 ) bolt10 0 0 0 1 1
|
||||||
|
( 704 1088 944 ) ( 705 1088 944 ) ( 704 1089 944 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1216 1008 ) ( 720 1217 1008 ) ( 721 1216 1008 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1216 960 ) ( 721 1216 960 ) ( 720 1216 961 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1216 960 ) ( 720 1216 961 ) ( 720 1217 960 ) bolt10 0 0 0 1 1
|
||||||
|
}
|
||||||
|
// brush 7
|
||||||
|
{
|
||||||
|
( 704 1088 944 ) ( 704 1089 944 ) ( 704 1088 945 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1344 960 ) ( 720 1344 961 ) ( 721 1344 960 ) bolt10 0 0 0 1 1
|
||||||
|
( 704 1088 944 ) ( 705 1088 944 ) ( 704 1089 944 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1216 1008 ) ( 720 1217 1008 ) ( 721 1216 1008 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1488 960 ) ( 721 1488 960 ) ( 720 1488 961 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1216 960 ) ( 720 1216 961 ) ( 720 1217 960 ) bolt10 0 0 0 1 1
|
||||||
|
}
|
||||||
|
// brush 8
|
||||||
|
{
|
||||||
|
( 704 1088 944 ) ( 704 1089 944 ) ( 704 1088 945 ) bolt10 0 0 0 1 1
|
||||||
|
( 704 1088 944 ) ( 704 1088 945 ) ( 705 1088 944 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1216 1008 ) ( 721 1216 1008 ) ( 720 1217 1008 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1216 1016 ) ( 720 1217 1016 ) ( 721 1216 1016 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1488 960 ) ( 721 1488 960 ) ( 720 1488 961 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1216 960 ) ( 720 1216 961 ) ( 720 1217 960 ) bolt10 0 0 0 1 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// entity 1
|
||||||
|
{
|
||||||
|
"classname" "info_player_start"
|
||||||
|
"origin" "848 1280 968"
|
||||||
|
"angle" "180"
|
||||||
|
}
|
||||||
|
// entity 2
|
||||||
|
{
|
||||||
|
"classname" "light"
|
||||||
|
"origin" "760 1280 1048"
|
||||||
|
"light" "1000"
|
||||||
|
"targetname" "toggle_door1_shadow"
|
||||||
|
"spawnflags" "1"
|
||||||
|
"_switchableshadow_target" "door1"
|
||||||
|
}
|
||||||
|
// entity 3
|
||||||
|
{
|
||||||
|
"classname" "light"
|
||||||
|
"origin" "568 1264 952"
|
||||||
|
"_color" "1 0 0"
|
||||||
|
"light" "500"
|
||||||
|
}
|
||||||
|
// entity 4
|
||||||
|
{
|
||||||
|
"classname" "func_door"
|
||||||
|
"targetname" "door1"
|
||||||
|
"spawnflags" "32"
|
||||||
|
"angle" "-2"
|
||||||
|
"speed" "1000"
|
||||||
|
// brush 0
|
||||||
|
{
|
||||||
|
( 704 1320 944 ) ( 704 1321 944 ) ( 704 1320 945 ) bolt10 -8 0 0 1 1
|
||||||
|
( 704 1320 944 ) ( 704 1320 945 ) ( 705 1320 944 ) bolt10 0 0 0 1 1
|
||||||
|
( 704 1320 944 ) ( 705 1320 944 ) ( 704 1321 944 ) bolt10 0 8 0 1 1
|
||||||
|
( 720 1448 1008 ) ( 720 1449 1008 ) ( 721 1448 1008 ) bolt10 0 8 0 1 1
|
||||||
|
( 720 1336 960 ) ( 721 1336 960 ) ( 720 1336 961 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1448 960 ) ( 720 1448 961 ) ( 720 1449 960 ) bolt10 -8 0 0 1 1
|
||||||
|
}
|
||||||
|
// brush 1
|
||||||
|
{
|
||||||
|
( 704 1224 944 ) ( 704 1225 944 ) ( 704 1224 945 ) bolt10 -8 0 0 1 1
|
||||||
|
( 704 1224 944 ) ( 704 1224 945 ) ( 705 1224 944 ) bolt10 0 0 0 1 1
|
||||||
|
( 704 1224 944 ) ( 705 1224 944 ) ( 704 1225 944 ) bolt10 0 8 0 1 1
|
||||||
|
( 720 1352 1008 ) ( 720 1353 1008 ) ( 721 1352 1008 ) bolt10 0 8 0 1 1
|
||||||
|
( 720 1240 960 ) ( 721 1240 960 ) ( 720 1240 961 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1352 960 ) ( 720 1352 961 ) ( 720 1353 960 ) bolt10 -8 0 0 1 1
|
||||||
|
}
|
||||||
|
// brush 2
|
||||||
|
{
|
||||||
|
( 704 1256 944 ) ( 704 1257 944 ) ( 704 1256 945 ) bolt10 -8 0 0 1 1
|
||||||
|
( 704 1256 944 ) ( 704 1256 945 ) ( 705 1256 944 ) bolt10 0 0 0 1 1
|
||||||
|
( 704 1256 944 ) ( 705 1256 944 ) ( 704 1257 944 ) bolt10 0 8 0 1 1
|
||||||
|
( 720 1384 1008 ) ( 720 1385 1008 ) ( 721 1384 1008 ) bolt10 0 8 0 1 1
|
||||||
|
( 720 1272 960 ) ( 721 1272 960 ) ( 720 1272 961 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1384 960 ) ( 720 1384 961 ) ( 720 1385 960 ) bolt10 -8 0 0 1 1
|
||||||
|
}
|
||||||
|
// brush 3
|
||||||
|
{
|
||||||
|
( 704 1288 944 ) ( 704 1289 944 ) ( 704 1288 945 ) bolt10 -8 0 0 1 1
|
||||||
|
( 704 1288 944 ) ( 704 1288 945 ) ( 705 1288 944 ) bolt10 0 0 0 1 1
|
||||||
|
( 704 1288 944 ) ( 705 1288 944 ) ( 704 1289 944 ) bolt10 0 8 0 1 1
|
||||||
|
( 720 1416 1008 ) ( 720 1417 1008 ) ( 721 1416 1008 ) bolt10 0 8 0 1 1
|
||||||
|
( 720 1304 960 ) ( 721 1304 960 ) ( 720 1304 961 ) bolt10 0 0 0 1 1
|
||||||
|
( 720 1416 960 ) ( 720 1416 961 ) ( 720 1417 960 ) bolt10 -8 0 0 1 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// entity 5
|
||||||
|
{
|
||||||
|
"classname" "func_button"
|
||||||
|
"target" "switch1"
|
||||||
|
"angle" "-2"
|
||||||
|
// brush 0
|
||||||
|
{
|
||||||
|
( 752 1288 952 ) ( 752 1289 952 ) ( 752 1288 953 ) swire2 -56 0 0 1 1
|
||||||
|
( 792 1272 944 ) ( 791 1272 944 ) ( 792 1272 945 ) swire2 48 0 180 1 -1
|
||||||
|
( 792 1248 944 ) ( 792 1249 944 ) ( 791 1248 944 ) swire2 -56 -48 90 1 1
|
||||||
|
( 744 1288 952 ) ( 743 1288 952 ) ( 744 1289 952 ) +0switch -8 -16 90 1 1
|
||||||
|
( 744 1288 952 ) ( 744 1288 953 ) ( 743 1288 952 ) swire2 48 0 180 1 -1
|
||||||
|
( 784 1248 944 ) ( 784 1248 945 ) ( 784 1249 944 ) swire2 -56 0 0 1 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// entity 6
|
||||||
|
{
|
||||||
|
"classname" "trigger_relay"
|
||||||
|
"origin" "760 1256 1000"
|
||||||
|
"targetname" "switch1"
|
||||||
|
"target" "door1"
|
||||||
|
}
|
||||||
|
// entity 7
|
||||||
|
{
|
||||||
|
"classname" "trigger_relay"
|
||||||
|
"origin" "760 1320 1000"
|
||||||
|
"targetname" "switch1"
|
||||||
|
"target" "toggle_door1_shadow"
|
||||||
|
}
|
||||||
|
|
@ -319,7 +319,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,
|
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 lit_variant_t *lit = nullptr,
|
const qvec3d &point, const qvec3d &normal = {0, 0, 0}, const lit_variant_t *lit = nullptr,
|
||||||
const bspxentries_t *bspx = nullptr)
|
const bspxentries_t *bspx = nullptr, int style = 0)
|
||||||
{
|
{
|
||||||
auto *face = BSP_FindFaceAtPoint(bsp, model, point, normal);
|
auto *face = BSP_FindFaceAtPoint(bsp, model, point, normal);
|
||||||
ASSERT_TRUE(face);
|
ASSERT_TRUE(face);
|
||||||
|
|
@ -340,7 +340,7 @@ static void CheckFaceLuxelAtPoint(const mbsp_t *bsp, const dmodelh2_t *model, co
|
||||||
const auto coord = extents.worldToLMCoord(point);
|
const auto coord = extents.worldToLMCoord(point);
|
||||||
const auto int_coord = qvec2i(round(coord[0]), round(coord[1]));
|
const auto int_coord = qvec2i(round(coord[0]), round(coord[1]));
|
||||||
|
|
||||||
const qvec3b sample = LM_Sample(bsp, face, lit, extents, offset, int_coord);
|
const qvec3b sample = LM_Sample(bsp, face, lit, extents, offset, int_coord, style);
|
||||||
SCOPED_TRACE(fmt::format("world point: {}", point));
|
SCOPED_TRACE(fmt::format("world point: {}", point));
|
||||||
SCOPED_TRACE(fmt::format("lm coord: {}", coord));
|
SCOPED_TRACE(fmt::format("lm coord: {}", coord));
|
||||||
SCOPED_TRACE(fmt::format("lm int_coord: {}", int_coord));
|
SCOPED_TRACE(fmt::format("lm int_coord: {}", int_coord));
|
||||||
|
|
@ -1145,4 +1145,35 @@ TEST(ltfaceQ1, hdr)
|
||||||
// check internal lightmap - greyscale, since Q1
|
// check internal lightmap - greyscale, since Q1
|
||||||
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {0, 0, 0}, testpoint, testnormal);
|
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {0, 0, 0}, testpoint, testnormal);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ltfaceQ1, switchableshadowTarget)
|
||||||
|
{
|
||||||
|
SCOPED_TRACE("Vanilla-compatible switchable shadows");
|
||||||
|
|
||||||
|
auto [bsp, bspx, lit] = QbspVisLight_Q1("q1_light_switchableshadow_target.map", {});
|
||||||
|
|
||||||
|
// find the light controlling the switchable shadow
|
||||||
|
auto entdicts = EntData_Parse(bsp);
|
||||||
|
|
||||||
|
auto it = std::find_if(entdicts.begin(), entdicts.end(), [](const entdict_t& dict) -> bool {
|
||||||
|
return dict.get("_switchableshadow_target") == "door1";
|
||||||
|
});
|
||||||
|
ASSERT_NE(it, entdicts.end());
|
||||||
|
|
||||||
|
ASSERT_TRUE(it->has("style"));
|
||||||
|
int switchable_style = it->get_int("style");
|
||||||
|
|
||||||
|
ASSERT_EQ(32, switchable_style);
|
||||||
|
|
||||||
|
const qvec3f not_in_shadow {792, 1240, 944};
|
||||||
|
const qvec3f in_shadow {792, 1264, 944};
|
||||||
|
|
||||||
|
// not in shadow - should be lit up red in style 0, and black in style 32
|
||||||
|
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {68, 0, 0}, not_in_shadow, {0, 0, 1}, &lit, &bspx, 0);
|
||||||
|
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {0, 0, 0}, not_in_shadow, {0, 0, 1}, &lit, &bspx, 32);
|
||||||
|
|
||||||
|
// in (switchable) shadow - should be black in style 0, and red in style 32
|
||||||
|
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {0, 0, 0}, in_shadow, {0, 0, 1}, &lit, &bspx, 0);
|
||||||
|
CheckFaceLuxelAtPoint(&bsp, &bsp.dmodels[0], {68, 0, 0}, in_shadow, {0, 0, 1}, &lit, &bspx, 32);
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue