From 74269a026917ba923307bb4cc1259531bb1f9c47 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Tue, 8 Nov 2022 22:03:52 -0700 Subject: [PATCH 01/23] light: new Mottle implementation based on world-space "value noise" --- include/light/light.hh | 4 +- light/light.cc | 9 ++- light/ltface.cc | 126 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 136 insertions(+), 3 deletions(-) diff --git a/include/light/light.hh b/include/light/light.hh index ad6abc50..f117a8ad 100644 --- a/include/light/light.hh +++ b/include/light/light.hh @@ -161,7 +161,8 @@ enum class debugmodes debugoccluded, debugneighbours, phong_tangents, - phong_bitangents + phong_bitangents, + mottle }; enum class lightfile @@ -385,6 +386,7 @@ public: setting_func phongdebug_obj; setting_func debugoccluded; setting_func debugneighbours; + setting_func debugmottle; light_settings(); diff --git a/light/light.cc b/light/light.cc index 45704665..52be1f05 100644 --- a/light/light.cc +++ b/light/light.cc @@ -351,7 +351,14 @@ light_settings::light_settings() CheckNoDebugModeSet(); debugmode = debugmodes::debugneighbours; }, - &debug_group, "save neighboring faces data to lightmap (requires -debugface)"} + &debug_group, "save neighboring faces data to lightmap (requires -debugface)"}, + + debugmottle{this, "debugmottle", + [&](source) { + CheckNoDebugModeSet(); + debugmode = debugmodes::mottle; + }, + &debug_group, "save mottle pattern to lightmap"} { } diff --git a/light/ltface.cc b/light/ltface.cc index e26d0ad2..f4b11634 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -1395,6 +1395,110 @@ static void LightFace_Sky(const sun_t *sun, lightsurf_t *lightsurf, lightmapdict } } +// Mottle + +static int mod_round_to_neg_inf(int x, int y) { + assert(y > 0); + if (x >= 0) { + return x % y; + } + // e.g. with mod_round_to_neg_inf(-7, 3) we want +2 + const int temp = (-x) % y; + return y - temp; +} + +constexpr int mottle_texsize = 256; + +/** + * integers 0 through 255 shuffled with Python: + * + * import random + * a = list(range(0, 256)) + * random.shuffle(a) + */ +static constexpr uint8_t MottlePermutation256[] = {11, 255, 250, 82, 217, 9, 144, 93, 136, 153, 55, 71, 73, 204, 96, + 180, 126, 8, 50, 46, 113, 91, 238, 143, 30, 215, 191, 243, 65, 58, 208, 33, 86, 1, 182, 118, 83, 115, 207, 52, 94, + 112, 205, 48, 99, 254, 117, 101, 157, 140, 72, 242, 244, 154, 10, 135, 155, 168, 125, 183, 148, 116, 187, 166, 25, + 156, 177, 231, 165, 57, 221, 105, 28, 211, 127, 41, 142, 253, 146, 87, 122, 229, 162, 137, 194, 174, 167, 15, 220, + 26, 235, 3, 39, 80, 88, 42, 202, 12, 97, 53, 70, 123, 170, 110, 214, 192, 173, 84, 169, 188, 64, 102, 147, 158, 100, + 69, 213, 193, 43, 20, 13, 237, 171, 103, 32, 190, 223, 150, 131, 206, 85, 124, 163, 18, 139, 132, 79, 29, 216, 232, + 178, 74, 24, 141, 201, 181, 152, 4, 7, 159, 134, 212, 226, 245, 164, 239, 47, 66, 27, 40, 197, 81, 78, 219, 228, + 241, 121, 23, 120, 230, 76, 252, 199, 184, 45, 203, 161, 89, 16, 21, 119, 5, 209, 196, 68, 130, 195, 176, 225, 233, + 128, 22, 248, 179, 249, 61, 108, 138, 145, 31, 49, 107, 56, 172, 224, 210, 6, 160, 189, 104, 200, 44, 175, 133, 77, + 62, 106, 92, 186, 227, 14, 38, 247, 37, 17, 222, 36, 75, 129, 185, 251, 240, 54, 151, 2, 98, 149, 0, 63, 218, 60, + 198, 19, 59, 90, 246, 234, 67, 51, 109, 95, 236, 35, 34, 114, 111}; + +/** + * Return a noise texture value from 0-47. + * + * Vanilla Q2 tools just called (rand() % 48) per-luxel, which generates seams + * and scales in size with lightmap scale. + * + * Replacement code uses "value noise", generating a tiling 3D texture + * in world space. + */ +static float Mottle(const qvec3d &position) +{ +#if 0 + return rand() % 48; +#else + const float world_to_tex = 1/16.0f; + + qvec3d texspace_pos = position * world_to_tex; + + int coord_floor_x = static_cast(floor(texspace_pos[0])); + int coord_floor_y = static_cast(floor(texspace_pos[1])); + int coord_floor_z = static_cast(floor(texspace_pos[2])); + + float coord_frac_x = static_cast(texspace_pos[0] - coord_floor_x); + float coord_frac_y = static_cast(texspace_pos[1] - coord_floor_y); + float coord_frac_z = static_cast(texspace_pos[2] - coord_floor_z); + + assert(coord_frac_x >= 0 && coord_frac_x <= 1); + assert(coord_frac_y >= 0 && coord_frac_y <= 1); + assert(coord_frac_z >= 0 && coord_frac_z <= 1); + + coord_floor_x = mod_round_to_neg_inf(coord_floor_x, mottle_texsize); + coord_floor_y = mod_round_to_neg_inf(coord_floor_y, mottle_texsize); + coord_floor_z = mod_round_to_neg_inf(coord_floor_z, mottle_texsize); + + assert(coord_floor_x >= 0 && coord_floor_x < mottle_texsize); + assert(coord_floor_y >= 0 && coord_floor_y < mottle_texsize); + assert(coord_floor_z >= 0 && coord_floor_z < mottle_texsize); + + // look up sample in the 3d texture at an integer coordinate + auto tex = [](int x, int y, int z) -> uint8_t { + int v; + v = MottlePermutation256[x % 256]; + v = MottlePermutation256[(v + y) % 256]; + v = MottlePermutation256[(v + z) % 256]; + return v; + }; + + // 3D bilinear interpolation + float res = mix( + mix( + mix(tex(coord_floor_x, coord_floor_y, coord_floor_z), + tex(coord_floor_x + 1, coord_floor_y, coord_floor_z), + coord_frac_x), + mix(tex(coord_floor_x, coord_floor_y + 1, coord_floor_z), + tex(coord_floor_x + 1, coord_floor_y + 1, coord_floor_z), + coord_frac_x), + coord_frac_y), + mix( + mix(tex(coord_floor_x, coord_floor_y, coord_floor_z + 1), + tex(coord_floor_x + 1, coord_floor_y, coord_floor_z + 1), + coord_frac_x), + mix(tex(coord_floor_x, coord_floor_y + 1, coord_floor_z + 1), + tex(coord_floor_x + 1, coord_floor_y + 1, coord_floor_z + 1), + coord_frac_x), + coord_frac_y), + coord_frac_z); + + return (res / 255.0f) * 48.0f; +#endif +} + /* * ============ * LightFace_Min @@ -1425,7 +1529,7 @@ static void LightFace_Min(const mbsp_t *bsp, const mface_t *face, const qvec3d & sample.color += color * (value / 255.0); } else { if (lightsurf->minlightMottle) { - value += rand() % 48; + value += Mottle(lightsurf->points[i]); } Light_ClampMin(sample, value, color); } @@ -1563,6 +1667,23 @@ static void LightFace_PhongDebug(const lightsurf_t *lightsurf, lightmapdict_t *l Lightmap_Save(lightmaps, lightsurf, lightmap, 0); } +static void LightFace_DebugMottle(const lightsurf_t *lightsurf, lightmapdict_t *lightmaps) +{ + /* use a style 0 light map */ + lightmap_t *lightmap = Lightmap_ForStyle(lightmaps, 0, lightsurf); + + /* Overwrite each point with the mottle noise for that sample... */ + for (int i = 0; i < lightsurf->points.size(); i++) { + lightsample_t &sample = lightmap->samples[i]; + // mottle is meant to be applied on top of minlight, so add some here + // for preview purposes. + const float minlight = 20.0f; + sample.color = qvec3f(minlight + Mottle(lightsurf->points[i])); + } + + Lightmap_Save(lightmaps, lightsurf, lightmap, 0); +} + // mxd. Surface light falloff. Returns color in [0,255] inline qvec3f SurfaceLight_ColorAtDist( const settings::worldspawn_keys &cfg, const float &surf_scale, const float &intensity, const qvec3d &color, const float &dist, const float &hotspot_clamp) @@ -2888,6 +3009,9 @@ void DirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings:: if (light_options.debugmode == debugmodes::debugneighbours) LightFace_DebugNeighbours(&lightsurf, lightmaps); + + if (light_options.debugmode == debugmodes::mottle) + LightFace_DebugMottle(&lightsurf, lightmaps); } /* From 93d059058f3b6ee3d9e57a66734fb3790e61f343 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Thu, 10 Nov 2022 09:57:43 -0700 Subject: [PATCH 02/23] testqbsp: fix mirrorinside + bmodels in Q1 mode --- qbsp/brush.cc | 17 +--- .../qbsp_bmodel_mirrorinside_with_liquid.map | 97 +++++++++++++++++++ tests/test_qbsp.cc | 13 +++ 3 files changed, 115 insertions(+), 12 deletions(-) create mode 100644 testmaps/qbsp_bmodel_mirrorinside_with_liquid.map diff --git a/qbsp/brush.cc b/qbsp/brush.cc index 9e8f0217..1205b6e9 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -779,19 +779,12 @@ static void Brush_LoadEntity(mapentity_t &dst, mapentity_t &src, hull_index_t hu /* entities in some games never use water merging */ if (!map.is_world_entity(dst) && !qbsp_options.target_game->allow_contented_bmodels) { - contents = qbsp_options.target_game->create_solid_contents(); + // bmodels become solid in Q1 - /* Hack to turn bmodels with "_mirrorinside" into func_detail_fence in hull 0. - this is to allow "_mirrorinside" to work on func_illusionary, func_wall, etc. - Otherwise they would be CONTENTS_SOLID and the inside faces would be deleted. - - It's CONTENTS_DETAIL_FENCE because this gets mapped to CONTENTS_SOLID just - before writing the bsp, and bmodels normally have CONTENTS_SOLID as their - contents type. - */ - if (!hullnum.value_or(0) && contents.is_mirrored(qbsp_options.target_game)) { - contents = qbsp_options.target_game->create_detail_fence_contents(contents); - } + // to allow use of _mirrorinside, we'll set it to detail fence, which will get remapped back + // to CONTENTS_SOLID at export. (we wouldn't generate inside faces if the content was CONTENTS_SOLID + // from the start.) + contents = qbsp_options.target_game->create_detail_fence_contents(qbsp_options.target_game->create_solid_contents()); } if (hullnum.value_or(0)) { diff --git a/testmaps/qbsp_bmodel_mirrorinside_with_liquid.map b/testmaps/qbsp_bmodel_mirrorinside_with_liquid.map new file mode 100644 index 00000000..d35519ba --- /dev/null +++ b/testmaps/qbsp_bmodel_mirrorinside_with_liquid.map @@ -0,0 +1,97 @@ +// Game: Quake +// Format: Valve +// entity 0 +{ +"mapversion" "220" +"classname" "worldspawn" +"wad" "deprecated/free_wad.wad;deprecated/fence.wad;deprecated/origin.wad;deprecated/hintskip.wad" +"_wateralpha" "0.5" +"_tb_def" "builtin:Quake.fgd" +// brush 0 +{ +( -112 -112 96 ) ( -112 -111 96 ) ( -112 -112 97 ) orangestuff8 [ 0 1 0 -16 ] [ 0 0 -1 0 ] 0 2 2 +( -80 -272 80 ) ( -81 -272 80 ) ( -80 -272 81 ) orangestuff8 [ -1 0 0 16 ] [ 0 0 -1 0 ] 180 2 2 +( -80 -432 80 ) ( -80 -431 80 ) ( -81 -432 80 ) orangestuff8 [ 1 0 0 -16 ] [ 0 -1 0 16 ] 180 2 2 +( -160 -112 96 ) ( -161 -112 96 ) ( -160 -111 96 ) orangestuff8 [ -1 0 0 16 ] [ 0 -1 0 16 ] 180 2 2 +( -160 0 96 ) ( -160 0 97 ) ( -161 0 96 ) orangestuff8 [ 1 0 0 -16 ] [ 0 0 -1 0 ] 180 2 2 +( 64 -432 80 ) ( 64 -432 81 ) ( 64 -431 80 ) orangestuff8 [ 0 -1 0 16 ] [ 0 0 -1 0 ] 0 2 2 +} +// brush 1 +{ +( -112 -96 96 ) ( -112 -95 96 ) ( -112 -96 97 ) orangestuff8 [ 0 1 0 -16 ] [ 0 0 -1 0 ] 0 2 2 +( -80 0 80 ) ( -81 0 80 ) ( -80 0 81 ) orangestuff8 [ -1 0 0 16 ] [ 0 0 -1 0 ] 180 2 2 +( -80 -416 80 ) ( -80 -415 80 ) ( -81 -416 80 ) orangestuff8 [ 1 0 0 -16 ] [ 0 -1 0 16 ] 180 2 2 +( -160 -96 224 ) ( -161 -96 224 ) ( -160 -95 224 ) orangestuff8 [ -1 0 0 16 ] [ 0 -1 0 16 ] 180 2 2 +( -160 16 96 ) ( -160 16 97 ) ( -161 16 96 ) orangestuff8 [ 1 0 0 -16 ] [ 0 0 -1 0 ] 180 2 2 +( 64 -416 80 ) ( 64 -416 81 ) ( 64 -415 80 ) orangestuff8 [ 0 -1 0 16 ] [ 0 0 -1 0 ] 0 2 2 +} +// brush 2 +{ +( -112 -384 96 ) ( -112 -383 96 ) ( -112 -384 97 ) orangestuff8 [ 0 1 0 8 ] [ 0 0 -1 0 ] 0 2 2 +( -80 -288 80 ) ( -81 -288 80 ) ( -80 -288 81 ) orangestuff8 [ -1 0 0 16 ] [ 0 0 -1 0 ] 180 2 2 +( -80 -704 80 ) ( -80 -703 80 ) ( -81 -704 80 ) orangestuff8 [ 1 0 0 -16 ] [ 0 -1 0 -8 ] 180 2 2 +( -160 -384 224 ) ( -161 -384 224 ) ( -160 -383 224 ) orangestuff8 [ -1 0 0 16 ] [ 0 -1 0 -8 ] 180 2 2 +( -160 -272 96 ) ( -160 -272 97 ) ( -161 -272 96 ) orangestuff8 [ 1 0 0 -16 ] [ 0 0 -1 0 ] 180 2 2 +( 64 -704 80 ) ( 64 -704 81 ) ( 64 -703 80 ) orangestuff8 [ 0 -1 0 -8 ] [ 0 0 -1 0 ] 0 2 2 +} +// brush 3 +{ +( -128 -112 96 ) ( -128 -111 96 ) ( -128 -112 97 ) orangestuff8 [ 0 1 0 -16 ] [ 0 0 -1 0 ] 0 2 2 +( -256 -272 80 ) ( -257 -272 80 ) ( -256 -272 81 ) orangestuff8 [ -1 0 0 16 ] [ 0 0 -1 0 ] 180 2 2 +( -256 -432 80 ) ( -256 -431 80 ) ( -257 -432 80 ) orangestuff8 [ 1 0 0 -16 ] [ 0 -1 0 16 ] 180 2 2 +( -336 -112 224 ) ( -337 -112 224 ) ( -336 -111 224 ) orangestuff8 [ -1 0 0 16 ] [ 0 -1 0 16 ] 180 2 2 +( -336 0 96 ) ( -336 0 97 ) ( -337 0 96 ) orangestuff8 [ 1 0 0 -16 ] [ 0 0 -1 0 ] 180 2 2 +( -112 -432 80 ) ( -112 -432 81 ) ( -112 -431 80 ) orangestuff8 [ 0 -1 0 16 ] [ 0 0 -1 0 ] 0 2 2 +} +// brush 4 +{ +( 64 -112 96 ) ( 64 -111 96 ) ( 64 -112 97 ) orangestuff8 [ 0 1 0 -16 ] [ 0 0 -1 0 ] 0 2 2 +( -64 -272 80 ) ( -65 -272 80 ) ( -64 -272 81 ) orangestuff8 [ -1 0 0 16 ] [ 0 0 -1 0 ] 180 2 2 +( -64 -432 80 ) ( -64 -431 80 ) ( -65 -432 80 ) orangestuff8 [ 1 0 0 -16 ] [ 0 -1 0 16 ] 180 2 2 +( -144 -112 224 ) ( -145 -112 224 ) ( -144 -111 224 ) orangestuff8 [ -1 0 0 16 ] [ 0 -1 0 16 ] 180 2 2 +( -144 0 96 ) ( -144 0 97 ) ( -145 0 96 ) orangestuff8 [ 1 0 0 -16 ] [ 0 0 -1 0 ] 180 2 2 +( 80 -432 80 ) ( 80 -432 81 ) ( 80 -431 80 ) orangestuff8 [ 0 -1 0 16 ] [ 0 0 -1 0 ] 0 2 2 +} +// brush 5 +{ +( -112 -112 240 ) ( -112 -111 240 ) ( -112 -112 241 ) orangestuff8 [ 0 1 0 -16 ] [ 0 0 -1 0 ] 0 2 2 +( -80 -272 224 ) ( -81 -272 224 ) ( -80 -272 225 ) orangestuff8 [ -1 0 0 16 ] [ 0 0 -1 0 ] 180 2 2 +( -80 -432 224 ) ( -80 -431 224 ) ( -81 -432 224 ) orangestuff8 [ 1 0 0 -16 ] [ 0 -1 0 16 ] 180 2 2 +( -160 -112 240 ) ( -161 -112 240 ) ( -160 -111 240 ) orangestuff8 [ -1 0 0 16 ] [ 0 -1 0 16 ] 180 2 2 +( -160 0 240 ) ( -160 0 241 ) ( -161 0 240 ) orangestuff8 [ 1 0 0 -16 ] [ 0 0 -1 0 ] 180 2 2 +( 64 -432 224 ) ( 64 -432 225 ) ( 64 -431 224 ) orangestuff8 [ 0 -1 0 16 ] [ 0 0 -1 0 ] 0 2 2 +} +} +// entity 1 +{ +"classname" "info_player_start" +"origin" "-88 -64 120" +} +// entity 2 +{ +"classname" "func_wall" +"_mirrorinside" "1" +// brush 0 +{ +( -16 -76 112 ) ( -16 -75 112 ) ( -16 -76 113 ) {trigger [ 0 -1 0 -16 ] [ 0 0 -1 16 ] 0 1 1 +( -8 -80 112 ) ( -8 -80 113 ) ( -7 -80 112 ) {trigger [ 1 0 0 16 ] [ 0 0 -1 16 ] 0 1 1 +( -8 -76 112 ) ( -7 -76 112 ) ( -8 -75 112 ) {trigger [ -1 0 0 -16 ] [ 0 -1 0 -16 ] 0 1 1 +( 56 -28 208 ) ( 56 -27 208 ) ( 57 -28 208 ) {trigger [ 1 0 0 16 ] [ 0 -1 0 -16 ] 0 1 1 +( 56 -32 128 ) ( 57 -32 128 ) ( 56 -32 129 ) {trigger [ -1 0 0 -16 ] [ 0 0 -1 16 ] 0 1 1 +( 32 -28 128 ) ( 32 -28 129 ) ( 32 -27 128 ) {trigger [ 0 1 0 16 ] [ 0 0 -1 16 ] 0 1 1 +} +} +// entity 3 +{ +"classname" "func_wall" +"_mirrorinside" "1" +// brush 0 +{ +( -16 -140 112 ) ( -16 -139 112 ) ( -16 -140 113 ) *swater4 [ 0 -1 0 -16 ] [ 0 0 -1 16 ] 0 1 1 +( -8 -144 112 ) ( -8 -144 113 ) ( -7 -144 112 ) *swater4 [ 1 0 0 16 ] [ 0 0 -1 16 ] 0 1 1 +( -8 -140 112 ) ( -7 -140 112 ) ( -8 -139 112 ) *swater4 [ -1 0 0 -16 ] [ 0 -1 0 -16 ] 0 1 1 +( 56 -92 208 ) ( 56 -91 208 ) ( 57 -92 208 ) *swater4 [ 1 0 0 16 ] [ 0 -1 0 -16 ] 0 1 1 +( 56 -96 128 ) ( 57 -96 128 ) ( 56 -96 129 ) *swater4 [ -1 0 0 -16 ] [ 0 0 -1 16 ] 0 1 1 +( 32 -92 128 ) ( 32 -92 129 ) ( 32 -91 128 ) *swater4 [ 0 1 0 16 ] [ 0 0 -1 16 ] 0 1 1 +} +} diff --git a/tests/test_qbsp.cc b/tests/test_qbsp.cc index f020cc54..4373a785 100644 --- a/tests/test_qbsp.cc +++ b/tests/test_qbsp.cc @@ -822,6 +822,19 @@ TEST_CASE("water_detail_illusionary" * doctest::test_suite("testmaps_q1")) } } +TEST_CASE("qbsp_bmodel_mirrorinside_with_liquid" * doctest::test_suite("testmaps_q1")) +{ + const auto [bsp, bspx, prt] = LoadTestmapQ1("qbsp_bmodel_mirrorinside_with_liquid.map"); + + REQUIRE(prt.has_value()); + + const qvec3d model1_fenceface{-16, -56, 168}; + const qvec3d model2_waterface{-16, -120, 168}; + + CHECK(2 == BSP_FindFacesAtPoint(&bsp, &bsp.dmodels[1], model1_fenceface).size()); + CHECK(2 == BSP_FindFacesAtPoint(&bsp, &bsp.dmodels[2], model2_waterface).size()); +} + TEST_CASE("noclipfaces" * doctest::test_suite("testmaps_q1")) { const auto [bsp, bspx, prt] = LoadTestmapQ1("qbsp_noclipfaces.map"); From 3dc98bdef4041b616cd942a56bc21f86808d92cd Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Fri, 11 Nov 2022 13:11:50 -0700 Subject: [PATCH 03/23] appveyor: use vs2022 image --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index d514f219..b181162b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,5 +1,5 @@ image: - - Visual Studio 2019 + - Visual Studio 2022 platform: - x64 From 61f2bd84cfaec747799d0a836125dea597124422 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Fri, 11 Nov 2022 13:29:48 -0700 Subject: [PATCH 04/23] appveyor: use v143 toolchain --- build-appveyor.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-appveyor.ps1 b/build-appveyor.ps1 index 5c91680a..b76e1b7d 100644 --- a/build-appveyor.ps1 +++ b/build-appveyor.ps1 @@ -18,7 +18,7 @@ mkdir cmakebuild cd cmakebuild -cmake .. -T v142 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" +cmake .. -T v143 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" $cmakePlatform = "x64" From b81b52da5a1c59ac4e018ba039dcd409df8560a5 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Fri, 11 Nov 2022 15:04:53 -0700 Subject: [PATCH 05/23] qbsp: fix nonsolid bmodels in hul1/2 --- qbsp/brush.cc | 10 +++++----- tests/test_qbsp.cc | 10 ++++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/qbsp/brush.cc b/qbsp/brush.cc index 1205b6e9..f5f383db 100644 --- a/qbsp/brush.cc +++ b/qbsp/brush.cc @@ -789,14 +789,14 @@ static void Brush_LoadEntity(mapentity_t &dst, mapentity_t &src, hull_index_t hu if (hullnum.value_or(0)) { /* nonsolid brushes don't show up in clipping hulls */ - if (!contents.is_any_solid(qbsp_options.target_game) && !contents.is_sky(qbsp_options.target_game)) { + if (!contents.is_any_solid(qbsp_options.target_game) + && !contents.is_sky(qbsp_options.target_game) + && !contents.is_fence(qbsp_options.target_game)) { continue; } - /* sky brushes are solid in the collision hulls */ - if (contents.is_sky(qbsp_options.target_game)) { - contents = qbsp_options.target_game->create_solid_contents(); - } + /* all used brushes are solid in the collision hulls */ + contents = qbsp_options.target_game->create_solid_contents(); } // fixme-brushbsp: function calls above can override the values below diff --git a/tests/test_qbsp.cc b/tests/test_qbsp.cc index 4373a785..429ca765 100644 --- a/tests/test_qbsp.cc +++ b/tests/test_qbsp.cc @@ -833,6 +833,16 @@ TEST_CASE("qbsp_bmodel_mirrorinside_with_liquid" * doctest::test_suite("testmaps CHECK(2 == BSP_FindFacesAtPoint(&bsp, &bsp.dmodels[1], model1_fenceface).size()); CHECK(2 == BSP_FindFacesAtPoint(&bsp, &bsp.dmodels[2], model2_waterface).size()); + + // both bmodels should be CONTENTS_SOLID in all hulls + for (int model_idx = 1; model_idx <= 2; ++model_idx) { + for (int hull = 0; hull <= 2; ++hull) { + auto &model = bsp.dmodels[model_idx]; + + INFO("model: ", model_idx, " hull: ", hull); + CHECK(CONTENTS_SOLID == BSP_FindContentsAtPoint(&bsp, {hull}, &model, (model.mins + model.maxs) / 2)); + } + } } TEST_CASE("noclipfaces" * doctest::test_suite("testmaps_q1")) From a5125583fa730d9faa8c1b87a8c92624dfa375e2 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Fri, 11 Nov 2022 16:52:07 -0700 Subject: [PATCH 06/23] light: clear global data so light can run multiple times per process --- include/light/bounce.hh | 1 + include/light/entities.hh | 1 + include/light/light.hh | 1 + include/light/ltface.hh | 1 + include/light/phong.hh | 1 + include/light/surflight.hh | 1 + include/light/trace_embree.hh | 1 + light/bounce.cc | 6 +++++ light/entities.cc | 28 +++++++++++++++------ light/light.cc | 47 +++++++++++++++++++++++++++++++++++ light/ltface.cc | 18 ++++++++++++++ light/phong.cc | 11 ++++++++ light/surflight.cc | 7 ++++++ light/trace_embree.cc | 29 +++++++++++++++++---- 14 files changed, 141 insertions(+), 12 deletions(-) diff --git a/include/light/bounce.hh b/include/light/bounce.hh index 8c306812..448fd877 100644 --- a/include/light/bounce.hh +++ b/include/light/bounce.hh @@ -32,5 +32,6 @@ // public functions +void ResetBounce(); const std::vector &BounceLights(); void MakeBounceLights(const settings::worldspawn_keys &cfg, const mbsp_t *bsp); diff --git a/include/light/entities.hh b/include/light/entities.hh index f038cf5e..c5de03f8 100644 --- a/include/light/entities.hh +++ b/include/light/entities.hh @@ -122,6 +122,7 @@ public: * Stores the RGB values to determine the light color */ +void ResetLightEntities(); std::string TargetnameForLightStyle(int style); std::vector> &GetLights(); std::vector &GetSuns(); diff --git a/include/light/light.hh b/include/light/light.hh index f117a8ad..d2f04e54 100644 --- a/include/light/light.hh +++ b/include/light/light.hh @@ -427,5 +427,6 @@ const modelinfo_t *ModelInfoForFace(const mbsp_t *bsp, int facenum); const img::texture *Face_Texture(const mbsp_t *bsp, const mface_t *face); const qvec3b &Face_LookupTextureColor(const mbsp_t *bsp, const mface_t *face); const qvec3d &Face_LookupTextureBounceColor(const mbsp_t *bsp, const mface_t *face); +void light_reset(); int light_main(int argc, const char **argv); int light_main(const std::vector &args); diff --git a/include/light/ltface.hh b/include/light/ltface.hh index 70d8adf3..0f090963 100644 --- a/include/light/ltface.hh +++ b/include/light/ltface.hh @@ -61,3 +61,4 @@ void FinishLightmapSurface(const mbsp_t *bsp, lightsurf_t *lightsurf); void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, bspx_decoupled_lm_perface *facesup_decoupled, lightsurf_t *lightsurf, const faceextents_t &extents, const faceextents_t &output_extents); +void ResetLtFace(); diff --git a/include/light/phong.hh b/include/light/phong.hh index 341eb889..d2fbb674 100644 --- a/include/light/phong.hh +++ b/include/light/phong.hh @@ -79,3 +79,4 @@ public: }; const face_cache_t &FaceCacheForFNum(int fnum); +void ResetPhong(); diff --git a/include/light/surflight.hh b/include/light/surflight.hh index 532eeeaf..c04104e6 100644 --- a/include/light/surflight.hh +++ b/include/light/surflight.hh @@ -49,6 +49,7 @@ struct surfacelight_t bool rescale; }; +void ResetSurflight(); std::vector &GetSurfaceLights(); std::optional> IsSurfaceLitFace(const mbsp_t *bsp, const mface_t *face); const std::vector &SurfaceLightsForFaceNum(int facenum); diff --git a/include/light/trace_embree.hh b/include/light/trace_embree.hh index 219a3eac..05f73115 100644 --- a/include/light/trace_embree.hh +++ b/include/light/trace_embree.hh @@ -27,6 +27,7 @@ #include #include +void ResetEmbree(); void Embree_TraceInit(const mbsp_t *bsp); hitresult_t Embree_TestSky(const qvec3d &start, const qvec3d &dirn, const modelinfo_t *self, const mface_t **face_out); hitresult_t Embree_TestLight(const qvec3d &start, const qvec3d &stop, const modelinfo_t *self); diff --git a/light/bounce.cc b/light/bounce.cc index c74ecce1..974f6723 100644 --- a/light/bounce.cc +++ b/light/bounce.cc @@ -44,6 +44,12 @@ mutex bouncelights_lock; static std::vector bouncelights; static std::atomic_size_t bouncelightpoints; +void ResetBounce() +{ + bouncelights.clear(); + bouncelightpoints = 0; +} + static bool Face_ShouldBounce(const mbsp_t *bsp, const mface_t *face) { // make bounce light, only if this face is shadow casting diff --git a/light/entities.cc b/light/entities.cc index d413fb0a..637680dd 100644 --- a/light/entities.cc +++ b/light/entities.cc @@ -33,6 +33,27 @@ std::vector> all_lights; std::vector all_suns; std::vector entdicts; std::vector radlights; +static std::vector> lightstyleForTargetname; +static std::vector> surfacelight_templates; +static std::ofstream surflights_dump_file; +static fs::path surflights_dump_filename; + +/** + * Resets global data in this file + */ +void ResetLightEntities() +{ + all_lights.clear(); + all_suns.clear(); + entdicts.clear(); + radlights.clear(); + + lightstyleForTargetname.clear(); + + surfacelight_templates.clear(); + surflights_dump_file = {}; + surflights_dump_filename.clear(); +} std::vector> &GetLights() { @@ -104,8 +125,6 @@ void light_t::expandAABB(const qvec3d &pt) { bounds += pt; } * ============================================================================ */ -static std::vector> lightstyleForTargetname; - entdict_t &WorldEnt() { if (entdicts.size() == 0 || entdicts.at(0).get("classname") != "worldspawn") { @@ -1152,16 +1171,11 @@ void WriteEntitiesToString(const settings::worldspawn_keys &cfg, mbsp_t *bsp) * ======================================================================= */ -static std::vector> surfacelight_templates; - const std::vector> &GetSurfaceLightTemplates() { return surfacelight_templates; } -static std::ofstream surflights_dump_file; -static fs::path surflights_dump_filename; - static void SurfLights_WriteEntityToFile(light_t *entity, const qvec3d &pos) { Q_assert(entity->epairs != nullptr); diff --git a/light/light.cc b/light/light.cc index 52be1f05..a96a9cd2 100644 --- a/light/light.cc +++ b/light/light.cc @@ -1465,6 +1465,51 @@ void load_textures(const mbsp_t *bsp) } } +/** + * Resets globals in this file + */ +static void ResetLight() +{ + dirt_in_use = false; + light_surfaces.clear(); + faces_sup.clear(); + facesup_decoupled_global.clear(); + + filebase.clear(); + file_p = 0; + file_end = 0; + + lit_filebase.clear(); + lit_file_p = 0; + lit_file_end = 0; + + lux_filebase.clear(); + lux_file_p = 0; + lux_file_end = 0; + + modelinfo.clear(); + tracelist.clear(); + selfshadowlist.clear(); + shadowworldonlylist.clear(); + switchableshadowlist.clear(); + + extended_texinfo_flags.clear(); + + dump_facenum = -1; + dump_vertnum = -1; +} + +void light_reset() +{ + ResetBounce(); + ResetLightEntities(); + ResetLight(); + ResetLtFace(); + ResetPhong(); + ResetSurflight(); + ResetEmbree(); +} + /* * ================== * main @@ -1473,6 +1518,8 @@ void load_textures(const mbsp_t *bsp) */ int light_main(int argc, const char **argv) { + light_reset(); + bspdata_t bspdata; light_options.preinitialize(argc, argv); diff --git a/light/ltface.cc b/light/ltface.cc index f4b11634..13cc6e1e 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -1953,6 +1953,7 @@ void SetupDirt(settings::worldspawn_keys &cfg) /* iterate angle */ float angle = 0.0f; + numDirtVectors = 0; for (int i = 0; i < DIRT_NUM_ANGLE_STEPS; i++, angle += angleStep) { /* iterate elevation */ float elevation = elevationStep * 0.5f; @@ -3037,3 +3038,20 @@ void IndirectLightFace(const mbsp_t *bsp, lightsurf_t &lightsurf, const settings } } } + +void ResetLtFace() +{ + total_light_rays = 0; + total_light_ray_hits = 0; + total_samplepoints = 0; + + total_bounce_rays = 0; + total_bounce_ray_hits = 0; + total_surflight_rays = 0; + total_surflight_ray_hits = 0; + + fully_transparent_lightmaps = 0; + + warned_about_light_map_overflow = false; + warned_about_light_style_overflow = false; +} diff --git a/light/phong.cc b/light/phong.cc index 24e57edb..e9d793ef 100644 --- a/light/phong.cc +++ b/light/phong.cc @@ -182,6 +182,17 @@ static map> planesToFaces; static edgeToFaceMap_t EdgeToFaceMap; static vector FaceCache; +void ResetPhong() +{ + s_builtPhongCaches = false; + vertex_normals = {}; + smoothFaces = {}; + vertsToFaces = {}; + planesToFaces = {}; + EdgeToFaceMap = {}; + FaceCache = {}; +} + vector FacesUsingVert(int vertnum) { const auto &vertsToFaces_const = vertsToFaces; diff --git a/light/surflight.cc b/light/surflight.cc index 904a62ed..09288f4a 100644 --- a/light/surflight.cc +++ b/light/surflight.cc @@ -42,6 +42,13 @@ static std::vector surfacelights; static std::map> surfacelightsByFacenum; static size_t total_surflight_points = 0; +void ResetSurflight() +{ + surfacelights = {}; + surfacelightsByFacenum = {}; + total_surflight_points = {}; +} + std::vector &GetSurfaceLights() { return surfacelights; diff --git a/light/trace_embree.cc b/light/trace_embree.cc index 9290171c..65766ead 100644 --- a/light/trace_embree.cc +++ b/light/trace_embree.cc @@ -32,6 +32,30 @@ sceneinfo skygeom; // sky. always occludes. sceneinfo solidgeom; // solids. always occludes. sceneinfo filtergeom; // conditional occluders.. needs to run ray intersection filter +static RTCDevice device; +RTCScene scene; + +static const mbsp_t *bsp_static; + +void ResetEmbree() +{ + skygeom = {}; + solidgeom = {}; + filtergeom = {}; + + if (scene) { + rtcReleaseScene(scene); + scene = nullptr; + } + + if (device) { + rtcReleaseDevice(device); + device = nullptr; + } + + bsp_static = nullptr; +} + /** * Returns 1.0 unless a custom alpha value is set. * The priority is: "_light_alpha" (read from extended_texinfo_flags), then "alpha", then Q2 surface flags @@ -229,11 +253,6 @@ static void CreateGeometryFromWindings(RTCDevice g_device, RTCScene scene, const rtcCommitGeometry(geom_1); } -RTCDevice device; -RTCScene scene; - -static const mbsp_t *bsp_static; - void ErrorCallback(void *userptr, const RTCError code, const char *str) { fmt::print("RTC Error {}: {}\n", code, str); From d7acd046c32071470e5c8ba68ede5a4b2eaab7bc Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sat, 12 Nov 2022 17:07:02 -0700 Subject: [PATCH 07/23] light/qbsp: add _surflight_rescale key --- common/bspfile.cc | 4 +- common/bsputils.cc | 38 +++++++++++++ include/common/bspfile.hh | 4 ++ include/common/bsputils.hh | 5 ++ light/light.cc | 3 ++ light/surflight.cc | 4 +- qbsp/map.cc | 2 + qbsp/writebsp.cc | 3 ++ testmaps/light_q2_emissive_cube.map | 82 +++++++++++++++++++++++++++++ tests/test_ltface.cc | 53 ++++++++++++++++++- 10 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 testmaps/light_q2_emissive_cube.map diff --git a/common/bspfile.cc b/common/bspfile.cc index 9662ec5b..b9fa51c0 100644 --- a/common/bspfile.cc +++ b/common/bspfile.cc @@ -1693,14 +1693,14 @@ const bspversion_t bspver_qbism{Q2_QBISMIDENT, Q2_BSPVERSION, "qbism", "Quake II bool surfflags_t::needs_write() const { - return no_dirt || no_shadow || no_bounce || no_minlight || no_expand || light_ignore || phong_angle || + return no_dirt || no_shadow || no_bounce || no_minlight || no_expand || light_ignore || !surflight_rescale || phong_angle || phong_angle_concave || minlight || !qv::emptyExact(minlight_color) || light_alpha || maxlight || lightcolorscale != 1.0; } static auto as_tuple(const surfflags_t &flags) { return std::tie(flags.native, flags.is_nodraw, flags.is_hintskip, flags.is_hint, flags.no_dirt, flags.no_shadow, flags.no_bounce, flags.no_minlight, flags.no_expand, - flags.light_ignore, flags.phong_angle, flags.phong_angle_concave, flags.minlight, flags.minlight_color, flags.light_alpha, flags.maxlight, flags.lightcolorscale); + flags.light_ignore, flags.surflight_rescale, flags.phong_angle, flags.phong_angle_concave, flags.minlight, flags.minlight_color, flags.light_alpha, flags.maxlight, flags.lightcolorscale); } bool surfflags_t::operator<(const surfflags_t &other) const diff --git a/common/bsputils.cc b/common/bsputils.cc index 3182bf50..f3416c5e 100644 --- a/common/bsputils.cc +++ b/common/bsputils.cc @@ -622,6 +622,20 @@ void DecompressRow(const uint8_t *in, const int numbytes, uint8_t *decompressed) } while (out - decompressed < row); } +bspx_decoupled_lm_perface BSPX_DecoupledLM(const bspxentries_t &entries, int face_num) +{ + auto &lump_bytes = entries.at("DECOUPLED_LM"); + + auto stream = imemstream(lump_bytes.data(), lump_bytes.size()); + + stream.seekg(face_num * sizeof(bspx_decoupled_lm_perface)); + stream >> endianness; + + bspx_decoupled_lm_perface result; + stream >= result; + return result; +} + qvec2d WorldToTexCoord(const qvec3d &world, const mtexinfo_t *tex) { /* @@ -901,3 +915,27 @@ qvec3f faceextents_t::LMCoordToWorld(qvec2f lm) const const qvec4f res = lmToWorldMatrix * lmPadded; return res; } + +/** + * Samples the lightmap at an integer coordinate + */ +qvec3b LM_Sample(const mbsp_t *bsp, const faceextents_t &faceextents, int byte_offset_of_face, qvec2i coord) +{ + int pixel = coord[0] + (coord[1] * faceextents.width()); + + const uint8_t* data = bsp->dlightdata.data(); + + if (bsp->loadversion->game->has_rgb_lightmap) { + return qvec3f{ + data[byte_offset_of_face + (pixel * 3) + 0], + data[byte_offset_of_face + (pixel * 3) + 1], + data[byte_offset_of_face + (pixel * 3) + 2] + }; + } else { + return qvec3f{ + data[byte_offset_of_face + pixel], + data[byte_offset_of_face + pixel], + data[byte_offset_of_face + pixel] + }; + } +} \ No newline at end of file diff --git a/include/common/bspfile.hh b/include/common/bspfile.hh index b395fa73..86645554 100644 --- a/include/common/bspfile.hh +++ b/include/common/bspfile.hh @@ -185,6 +185,10 @@ struct surfflags_t // this face doesn't receive light bool light_ignore; + // if true, rescales any surface light emitted by these brushes to emit 50% light at 90 degrees from the surface normal + // if false, use a more natural angle falloff of 0% at 90 degrees + bool surflight_rescale = true; + // if non zero, enables phong shading and gives the angle threshold to use vec_t phong_angle; diff --git a/include/common/bsputils.hh b/include/common/bsputils.hh index f28cd115..f28876e7 100644 --- a/include/common/bsputils.hh +++ b/include/common/bsputils.hh @@ -20,6 +20,7 @@ #pragma once #include +#include #include #include #include @@ -107,6 +108,8 @@ void Face_DebugPrint(const mbsp_t *bsp, const mface_t *face); void CompressRow(const uint8_t *vis, const size_t numbytes, std::back_insert_iterator> it); void DecompressRow(const uint8_t *in, const int numbytes, uint8_t *decompressed); +bspx_decoupled_lm_perface BSPX_DecoupledLM(const bspxentries_t &entries, int face_num); + /* ======================================================================== */ qvec2d WorldToTexCoord(const qvec3d &world, const mtexinfo_t *tex); @@ -150,3 +153,5 @@ public: qvec2f worldToLMCoord(qvec3f world) const; qvec3f LMCoordToWorld(qvec2f lm) const; }; + +qvec3b LM_Sample(const mbsp_t *bsp, const faceextents_t &faceextents, int byte_offset_of_face, qvec2i coord); diff --git a/light/light.cc b/light/light.cc index a96a9cd2..f1adeb96 100644 --- a/light/light.cc +++ b/light/light.cc @@ -1072,6 +1072,9 @@ static void LoadExtendedTexinfoFlags(const fs::path &sourcefilename, const mbsp_ if (val.contains("light_ignore")) { flags.light_ignore = val.at("light_ignore").get(); } + if (val.contains("surflight_rescale")) { + flags.surflight_rescale = val.at("surflight_rescale").get(); + } if (val.contains("phong_angle")) { flags.phong_angle = val.at("phong_angle").get(); } diff --git a/light/surflight.cc b/light/surflight.cc index 09288f4a..0436022f 100644 --- a/light/surflight.cc +++ b/light/surflight.cc @@ -61,6 +61,8 @@ static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys auto poly = GLM_FacePoints(bsp, face); const float facearea = qv::PolyArea(poly.begin(), poly.end()); + const surfflags_t &extended_flags = extended_texinfo_flags[face->texinfo]; + // Avoid small, or zero-area faces if (facearea < 1) return; @@ -115,7 +117,7 @@ static void MakeSurfaceLight(const mbsp_t *bsp, const settings::worldspawn_keys l.omnidirectional = !is_directional; l.points = std::move(points); l.style = style; - l.rescale = true; + l.rescale = extended_flags.surflight_rescale; // Init bbox... if (light_options.visapprox.value() == visapprox_t::RAYS) { diff --git a/qbsp/map.cc b/qbsp/map.cc index 9233f344..b65e6e5c 100644 --- a/qbsp/map.cc +++ b/qbsp/map.cc @@ -576,6 +576,8 @@ static surfflags_t SurfFlagsForEntity(const maptexinfo_t &texinfo, const mapenti flags.no_minlight = true; if (entity.epairs.get_int("_lightignore") == 1) flags.light_ignore = true; + if (entity.epairs.has("_surflight_rescale") && entity.epairs.get_int("_surflight_rescale") == 0) + flags.surflight_rescale = false; // "_minlight_exclude", "_minlight_exclude2", "_minlight_exclude3"... for (int i = 0; i <= 9; i++) { diff --git a/qbsp/writebsp.cc b/qbsp/writebsp.cc index 8574b339..297e4323 100644 --- a/qbsp/writebsp.cc +++ b/qbsp/writebsp.cc @@ -368,6 +368,9 @@ static void WriteExtendedTexinfoFlags(void) if (tx.flags.light_ignore) { t["light_ignore"] = tx.flags.light_ignore; } + if (tx.flags.surflight_rescale == false) { + t["surflight_rescale"] = tx.flags.surflight_rescale; + } if (tx.flags.phong_angle) { t["phong_angle"] = tx.flags.phong_angle; } diff --git a/testmaps/light_q2_emissive_cube.map b/testmaps/light_q2_emissive_cube.map new file mode 100644 index 00000000..49891712 --- /dev/null +++ b/testmaps/light_q2_emissive_cube.map @@ -0,0 +1,82 @@ +// Game: Quake 2 +// Format: Quake2 (Valve) +// entity 0 +{ +"classname" "worldspawn" +"_tb_textures" "textures/e1u1" +"_bounce" "0" +// brush 0 +{ +( 928 -1072 880 ) ( 928 -1504 880 ) ( 928 -1504 864 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 928 -1504 880 ) ( 1120 -1504 880 ) ( 1120 -1504 864 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 1120 -1504 864 ) ( 1120 -1072 864 ) ( 928 -1072 864 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 928 -1072 880 ) ( 1120 -1072 880 ) ( 1120 -1504 880 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 1120 -1072 864 ) ( 1120 -1072 880 ) ( 928 -1072 880 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 1120 -1504 880 ) ( 1120 -1072 880 ) ( 1120 -1072 864 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +} +// brush 1 +{ +( 928 -1072 1040 ) ( 928 -1504 1040 ) ( 928 -1504 1024 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 928 -1504 1040 ) ( 1120 -1504 1040 ) ( 1120 -1504 1024 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 1120 -1504 1024 ) ( 1120 -1072 1024 ) ( 928 -1072 1024 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 928 -1072 1040 ) ( 1120 -1072 1040 ) ( 1120 -1504 1040 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 1120 -1072 1024 ) ( 1120 -1072 1040 ) ( 928 -1072 1040 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 1120 -1504 1040 ) ( 1120 -1072 1040 ) ( 1120 -1072 1024 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +} +// brush 2 +{ +( 1120 -1072 1024 ) ( 1120 -1504 1024 ) ( 1120 -1504 880 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 1120 -1504 1024 ) ( 1136 -1504 1024 ) ( 1136 -1504 880 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 1136 -1504 880 ) ( 1136 -1072 880 ) ( 1120 -1072 880 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 1120 -1072 1024 ) ( 1136 -1072 1024 ) ( 1136 -1504 1024 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 1136 -1072 880 ) ( 1136 -1072 1024 ) ( 1120 -1072 1024 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 1136 -1504 1024 ) ( 1136 -1072 1024 ) ( 1136 -1072 880 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +} +// brush 3 +{ +( 928 -1072 1024 ) ( 928 -1504 1024 ) ( 928 -1504 880 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 928 -1504 1024 ) ( 944 -1504 1024 ) ( 944 -1504 880 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 944 -1504 880 ) ( 944 -1072 880 ) ( 928 -1072 880 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 928 -1072 1024 ) ( 944 -1072 1024 ) ( 944 -1504 1024 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 944 -1072 880 ) ( 944 -1072 1024 ) ( 928 -1072 1024 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 944 -1504 1024 ) ( 944 -1072 1024 ) ( 944 -1072 880 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +} +// brush 4 +{ +( 944 -1072 1024 ) ( 944 -1088 1024 ) ( 944 -1088 880 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 944 -1088 1024 ) ( 1120 -1088 1024 ) ( 1120 -1088 880 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 1120 -1088 880 ) ( 1120 -1072 880 ) ( 944 -1072 880 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 944 -1072 1024 ) ( 1120 -1072 1024 ) ( 1120 -1088 1024 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 1120 -1072 880 ) ( 1120 -1072 1024 ) ( 944 -1072 1024 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 1120 -1088 1024 ) ( 1120 -1072 1024 ) ( 1120 -1072 880 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +} +// brush 5 +{ +( 936 -1504 1024 ) ( 936 -1520 1024 ) ( 936 -1520 880 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 936 -1520 1024 ) ( 1112 -1520 1024 ) ( 1112 -1520 880 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 1112 -1520 880 ) ( 1112 -1504 880 ) ( 936 -1504 880 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 936 -1504 1024 ) ( 1112 -1504 1024 ) ( 1112 -1520 1024 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 0 0 +( 1112 -1504 880 ) ( 1112 -1504 1024 ) ( 936 -1504 1024 ) e1u1/box3_7 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +( 1112 -1520 1024 ) ( 1112 -1504 1024 ) ( 1112 -1504 880 ) e1u1/box3_7 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 0 0 +} +} +// entity 1 +{ +"classname" "info_player_start" +"origin" "1040 -1184 904" +"angle" "270" +} +// entity 2 +{ +"classname" "func_group" +"_surflight_rescale" "0" +// brush 0 +{ +( 968 -1264 992 ) ( 968 -1464 992 ) ( 968 -1464 904 ) e1u1/box3_6 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 1 100 +( 968 -1464 992 ) ( 1104 -1464 992 ) ( 1104 -1464 904 ) e1u1/box3_6 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 1 100 +( 1104 -1464 904 ) ( 1104 -1264 904 ) ( 968 -1264 904 ) e1u1/box3_6 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 1 100 +( 968 -1264 992 ) ( 1104 -1264 992 ) ( 1104 -1464 992 ) e1u1/box3_6 [ 1 0 0 0 ] [ 0 -1 0 0 ] 0 1 1 0 1 100 +( 1104 -1264 904 ) ( 1104 -1264 992 ) ( 968 -1264 992 ) e1u1/box3_6 [ 1 0 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 1 100 +( 1104 -1464 992 ) ( 1104 -1264 992 ) ( 1104 -1264 904 ) e1u1/box3_6 [ 0 1 0 0 ] [ 0 0 -1 0 ] 0 1 1 0 1 100 +} +} diff --git a/tests/test_ltface.cc b/tests/test_ltface.cc index b81f0ce9..fee69fd4 100644 --- a/tests/test_ltface.cc +++ b/tests/test_ltface.cc @@ -5,7 +5,12 @@ #include #include -static void LoadTestmap(const std::filesystem::path &name, std::vector extra_args) +struct testresults_t { + mbsp_t bsp; + bspxentries_t bspx; +}; + +static testresults_t LoadTestmap(const std::filesystem::path &name, std::vector extra_args) { auto map_path = std::filesystem::path(testmaps_dir) / name; @@ -52,9 +57,53 @@ static void LoadTestmap(const std::filesystem::path &name, std::vector(bspdata.bsp), fs::path(qbsp_options.bsp_path).replace_extension(".bsp.json")); + + return {std::move(std::get(bspdata.bsp)), + std::move(bspdata.bspx.entries)}; } } TEST_CASE("TestLight") { - LoadTestmap("q2_lightmap_custom_scale.map", {"-threads", "1", "-extra", "-world_units_per_luxel", "8"}); + LoadTestmap("q2_lightmap_custom_scale.map", {"-threads", "1", "-world_units_per_luxel", "8"}); +} + +TEST_CASE("emissive cube artifacts") { + // A cube with surface flags "light", value "100", placed in a hallway. + // + // Generates harsh lines on the walls/ceiling due to a hack in `light` allowing + // surface lights to emit 50% at 90 degrees off their surface normal (when physically it should be 0%). + // + // It's wanted in some cases (base1.map sewer lights flush with the wall, desired for them to + // emit some lights on to their adjacent wall faces.) + // + // To disable the behaviour in this case with the cube lighting a hallway we have a entity key: + // + // "_surflight_rescale" "0" + // + auto [bsp, bspx] = LoadTestmap("light_q2_emissive_cube.map", {"-threads", "1", "-world_units_per_luxel", "4"}); + + const auto start = qvec3d{1044, -1244, 880}; + const auto end = qvec3d{1044, -1272, 880}; + + auto *floor = BSP_FindFaceAtPoint(&bsp, &bsp.dmodels[0], start, {0, 0, 1}); + auto lm_info = BSPX_DecoupledLM(bspx, Face_GetNum(&bsp, floor)); + + const faceextents_t extents(*floor, bsp, lm_info.lmwidth, lm_info.lmheight, lm_info.world_to_lm_space); + + // sample the lightmap along the floor, approaching the glowing cube + // should get brighter + qvec3b previous_sample{}; + for (int y = start[1]; y >= end[1]; y -= 4) { + qvec3d pos = start; + pos[1] = y; + + auto lm_coord = extents.worldToLMCoord(pos); + + auto sample = LM_Sample(&bsp, extents, lm_info.offset, lm_coord); + CHECK(sample[0] >= previous_sample[0]); + + //logging::print("world: {} lm_coord: {} sample: {} lm size: {}x{}\n", pos, lm_coord, sample, lm_info.lmwidth, lm_info.lmheight); + + previous_sample = sample; + } } From 276aa147dc4888a0dfcebede7c083fd99c062d2d Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sat, 12 Nov 2022 19:39:31 -0700 Subject: [PATCH 08/23] fix implicit qvec conversions reported as errors in Apple clang version 12.0.0 with std=c++2a mode --- tests/test_light.cc | 2 +- tests/test_qbsp.cc | 8 ++++---- tests/test_qbsp_q2.cc | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/test_light.cc b/tests/test_light.cc index 710b79d8..f9c9c9d9 100644 --- a/tests/test_light.cc +++ b/tests/test_light.cc @@ -188,7 +188,7 @@ TEST_CASE("PolygonCentroid") const std::initializer_list poly{{0, 0, 0}, {0, 32, 0}, // colinear {0, 64, 0}, {64, 64, 0}, {64, 0, 0}}; - CHECK(qvec3f(32, 32, 0) == qv::PolyCentroid(poly.begin(), poly.end())); + CHECK(qvec3d(32, 32, 0) == qv::PolyCentroid(poly.begin(), poly.end())); } TEST_CASE("PolygonArea") diff --git a/tests/test_qbsp.cc b/tests/test_qbsp.cc index 429ca765..d9d565f5 100644 --- a/tests/test_qbsp.cc +++ b/tests/test_qbsp.cc @@ -1146,7 +1146,7 @@ TEST_CASE("q1_cube") REQUIRE_FALSE(prt.has_value()); - const aabb3d cube_bounds { + const aabb3f cube_bounds { {32, -240, 80}, {80, -144, 112} }; @@ -1157,8 +1157,8 @@ TEST_CASE("q1_cube") // check the solid leaf auto& solid_leaf = bsp.dleafs[0]; - CHECK(solid_leaf.mins == qvec3d(0,0,0)); - CHECK(solid_leaf.maxs == qvec3d(0,0,0)); + CHECK(solid_leaf.mins == qvec3f(0,0,0)); + CHECK(solid_leaf.maxs == qvec3f(0,0,0)); // check the empty leafs for (int i = 1; i < 7; ++i) { @@ -1208,7 +1208,7 @@ TEST_CASE("q1_clip_func_wall" * doctest::test_suite("testmaps_q1")) REQUIRE(prt.has_value()); - const aabb3d cube_bounds { + const aabb3f cube_bounds { {64, 64, 48}, {128, 128, 80} }; diff --git a/tests/test_qbsp_q2.cc b/tests/test_qbsp_q2.cc index 1eef1618..4949f2a3 100644 --- a/tests/test_qbsp_q2.cc +++ b/tests/test_qbsp_q2.cc @@ -492,8 +492,8 @@ TEST_CASE("q2_door" * doctest::test_suite("testmaps_q2")) { CHECK(GAME_QUAKE_II == bsp.loadversion->game->id); - const aabb3d world_tight_bounds {{-64, -64, -16}, {64, 80, 128}}; - const aabb3d bmodel_tight_bounds {{-48, 48, 16}, {48, 64, 112}}; + const aabb3f world_tight_bounds {{-64, -64, -16}, {64, 80, 128}}; + const aabb3f bmodel_tight_bounds {{-48, 48, 16}, {48, 64, 112}}; CHECK(world_tight_bounds.mins() == bsp.dmodels[0].mins); CHECK(world_tight_bounds.maxs() == bsp.dmodels[0].maxs); From 8a9f32ca62f106ebc0c89540c3a1710202e71c9c Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sat, 12 Nov 2022 19:48:26 -0700 Subject: [PATCH 09/23] set CMAKE_CXX_STANDARD 20 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 50aa0f57..d92c6cd2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,7 +37,7 @@ if (UNIX) endif (UNIX) # set our C/C++ dialects -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD 99) From d28f97e6555a6d2b0b4cf838f00c3704bfbe6788 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sat, 12 Nov 2022 20:10:58 -0700 Subject: [PATCH 10/23] cmdlib: use include unconditionally --- include/common/cmdlib.hh | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/include/common/cmdlib.hh b/include/common/cmdlib.hh index 65e53e80..b4a93ae0 100644 --- a/include/common/cmdlib.hh +++ b/include/common/cmdlib.hh @@ -108,25 +108,8 @@ time_point I_FloatTime(); * BYTE ORDER FUNCTIONS * ============================================================================ */ -// C++20 polyfill -#if defined(__cpp_lib_endian) && __cpp_lib_endian >= 201907L -#include -#else -namespace std -{ -enum class endian -{ - little = 0, - big = 1, -#ifdef __BIG_ENDIAN__ - native = big -#else - native = little -#endif -}; -} // namespace std -#endif +#include // Binary streams; by default, streams use the native endianness // (unchanged bytes) but can be changed to a specific endianness From 4cbe63843f25116e972ace6caad65f4730c79ad9 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 13 Nov 2022 13:56:31 -0700 Subject: [PATCH 11/23] ci: try using -DCMAKE_SYSTEM_VERSION="8.1" to restore win8.1 support --- build-appveyor.ps1 | 2 +- build-windows.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build-appveyor.ps1 b/build-appveyor.ps1 index b76e1b7d..4bba61d3 100644 --- a/build-appveyor.ps1 +++ b/build-appveyor.ps1 @@ -18,7 +18,7 @@ mkdir cmakebuild cd cmakebuild -cmake .. -T v143 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" +cmake .. -T v143 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_SYSTEM_VERSION="8.1" -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" $cmakePlatform = "x64" diff --git a/build-windows.ps1 b/build-windows.ps1 index ecc6d24b..6909d9c7 100644 --- a/build-windows.ps1 +++ b/build-windows.ps1 @@ -20,7 +20,7 @@ choco install ninja mkdir build-windows cd build-windows -cmake .. -GNinja -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_BUILD_TYPE=Release +cmake .. -GNinja -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_VERSION="8.1" ninja if ( $? -eq $false ) { From d5c257536016f6a98ddb9ed1cbc2411c7a2edca1 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 13 Nov 2022 14:18:22 -0700 Subject: [PATCH 12/23] ci: try alternate way of requesting 8.1 sdk --- .github/workflows/cmake.yml | 2 ++ appveyor.yml | 1 + build-appveyor.ps1 | 2 +- build-windows.ps1 | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index eee59473..e1905aff 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -26,6 +26,8 @@ jobs: - name: Setup MSVC environment if: runner.os == 'Windows' uses: ilammy/msvc-dev-cmd@v1 + with: + sdk: 8.1 # maintain Windows 8.1 support - name: Linux Build if: runner.os == 'Linux' diff --git a/appveyor.yml b/appveyor.yml index b181162b..810bbf3e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,6 +9,7 @@ install: - ps: 7z x embree64.zip -oc:\ - ps: Invoke-WebRequest 'https://github.com/oneapi-src/oneTBB/releases/download/v2020.2/tbb-2020.2-win.zip' -OutFile 'tbb.zip' - ps: 7z x tbb.zip -oc:\ +- cmd: call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" x64 8.1 build_script: - cmd: powershell .\build-appveyor.ps1 artifacts: diff --git a/build-appveyor.ps1 b/build-appveyor.ps1 index 4bba61d3..b76e1b7d 100644 --- a/build-appveyor.ps1 +++ b/build-appveyor.ps1 @@ -18,7 +18,7 @@ mkdir cmakebuild cd cmakebuild -cmake .. -T v143 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_SYSTEM_VERSION="8.1" -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" +cmake .. -T v143 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" $cmakePlatform = "x64" diff --git a/build-windows.ps1 b/build-windows.ps1 index 6909d9c7..ecc6d24b 100644 --- a/build-windows.ps1 +++ b/build-windows.ps1 @@ -20,7 +20,7 @@ choco install ninja mkdir build-windows cd build-windows -cmake .. -GNinja -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_VERSION="8.1" +cmake .. -GNinja -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_BUILD_TYPE=Release ninja if ( $? -eq $false ) { From a7645c33961b0b7fd51a1dc73abe187e216f4970 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 13 Nov 2022 15:06:40 -0700 Subject: [PATCH 13/23] Revert "ci: try alternate way of requesting 8.1 sdk" This reverts commit d5c257536016f6a98ddb9ed1cbc2411c7a2edca1. --- .github/workflows/cmake.yml | 2 -- appveyor.yml | 1 - build-appveyor.ps1 | 2 +- build-windows.ps1 | 2 +- 4 files changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index e1905aff..eee59473 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -26,8 +26,6 @@ jobs: - name: Setup MSVC environment if: runner.os == 'Windows' uses: ilammy/msvc-dev-cmd@v1 - with: - sdk: 8.1 # maintain Windows 8.1 support - name: Linux Build if: runner.os == 'Linux' diff --git a/appveyor.yml b/appveyor.yml index 810bbf3e..b181162b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -9,7 +9,6 @@ install: - ps: 7z x embree64.zip -oc:\ - ps: Invoke-WebRequest 'https://github.com/oneapi-src/oneTBB/releases/download/v2020.2/tbb-2020.2-win.zip' -OutFile 'tbb.zip' - ps: 7z x tbb.zip -oc:\ -- cmd: call "C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" x64 8.1 build_script: - cmd: powershell .\build-appveyor.ps1 artifacts: diff --git a/build-appveyor.ps1 b/build-appveyor.ps1 index b76e1b7d..4bba61d3 100644 --- a/build-appveyor.ps1 +++ b/build-appveyor.ps1 @@ -18,7 +18,7 @@ mkdir cmakebuild cd cmakebuild -cmake .. -T v143 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" +cmake .. -T v143 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_SYSTEM_VERSION="8.1" -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" $cmakePlatform = "x64" diff --git a/build-windows.ps1 b/build-windows.ps1 index ecc6d24b..6909d9c7 100644 --- a/build-windows.ps1 +++ b/build-windows.ps1 @@ -20,7 +20,7 @@ choco install ninja mkdir build-windows cd build-windows -cmake .. -GNinja -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_BUILD_TYPE=Release +cmake .. -GNinja -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_VERSION="8.1" ninja if ( $? -eq $false ) { From eb4f25907ae98230efbd6b2ed05fb84d22069938 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 13 Nov 2022 15:07:27 -0700 Subject: [PATCH 14/23] Revert "ci: try using -DCMAKE_SYSTEM_VERSION="8.1" to restore win8.1 support" This reverts commit 4cbe63843f25116e972ace6caad65f4730c79ad9. --- build-appveyor.ps1 | 2 +- build-windows.ps1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build-appveyor.ps1 b/build-appveyor.ps1 index 4bba61d3..b76e1b7d 100644 --- a/build-appveyor.ps1 +++ b/build-appveyor.ps1 @@ -18,7 +18,7 @@ mkdir cmakebuild cd cmakebuild -cmake .. -T v143 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DCMAKE_SYSTEM_VERSION="8.1" -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" +cmake .. -T v143 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" $cmakePlatform = "x64" diff --git a/build-windows.ps1 b/build-windows.ps1 index 6909d9c7..ecc6d24b 100644 --- a/build-windows.ps1 +++ b/build-windows.ps1 @@ -20,7 +20,7 @@ choco install ninja mkdir build-windows cd build-windows -cmake .. -GNinja -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_VERSION="8.1" +cmake .. -GNinja -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_BUILD_TYPE=Release ninja if ( $? -eq $false ) { From 50c4709d3158756835666e050e6eeb9d989a23ff Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 13 Nov 2022 15:54:30 -0700 Subject: [PATCH 15/23] ci: use older embree/tbb which support Win8.1 --- .gitignore | 2 +- appveyor.yml | 5 ----- build-appveyor.ps1 | 9 ++++++++- build-windows.ps1 | 7 ++++--- light/CMakeLists.txt | 23 ++++++++++++++++++++--- tests/CMakeLists.txt | 10 +++++++++- 6 files changed, 42 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index bd4afd64..30bb64c0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ bin/ cmakebuild/ cmake-*/ -build*/ +*build*/ CMakeFiles/ *.xcodeproj .vscode/** diff --git a/appveyor.yml b/appveyor.yml index b181162b..48a06e6d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,11 +4,6 @@ platform: - x64 version: 1.0.{build} -install: -- ps: Invoke-WebRequest 'https://github.com/embree/embree/releases/download/v3.12.1/embree-3.12.1.x64.vc14.windows.zip' -OutFile 'embree64.zip' -- ps: 7z x embree64.zip -oc:\ -- ps: Invoke-WebRequest 'https://github.com/oneapi-src/oneTBB/releases/download/v2020.2/tbb-2020.2-win.zip' -OutFile 'tbb.zip' -- ps: 7z x tbb.zip -oc:\ build_script: - cmd: powershell .\build-appveyor.ps1 artifacts: diff --git a/build-appveyor.ps1 b/build-appveyor.ps1 index b76e1b7d..f87c4e88 100644 --- a/build-appveyor.ps1 +++ b/build-appveyor.ps1 @@ -1,3 +1,10 @@ +# Download embree and tbb +# Seems like TBB dropped Windows 8.1 support in version 2020 so we'll use older versions +Invoke-WebRequest 'https://github.com/embree/embree/releases/download/v3.9.0/embree-3.9.0.x64.vc14.windows.zip' -OutFile 'embree64.zip' +7z x embree64.zip -oc:\ +Invoke-WebRequest 'https://github.com/oneapi-src/oneTBB/releases/download/2019_U9/tbb2019_20191006oss_win.zip' -OutFile 'tbb.zip' +7z x tbb.zip -oc:\ + git submodule update --init --recursive $env:Path += ";C:\cygwin64\bin" @@ -18,7 +25,7 @@ mkdir cmakebuild cd cmakebuild -cmake .. -T v143 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" +cmake .. -T v143 -Dembree_DIR="C:\embree-3.9.0.x64.vc14.windows" -DTBB_DIR="C:\tbb2019_20191006oss\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DLEGACY_EMBREE=YES $cmakePlatform = "x64" diff --git a/build-windows.ps1 b/build-windows.ps1 index ecc6d24b..0df041fa 100644 --- a/build-windows.ps1 +++ b/build-windows.ps1 @@ -1,7 +1,8 @@ # Download embree and tbb -Invoke-WebRequest 'https://github.com/embree/embree/releases/download/v3.12.1/embree-3.12.1.x64.vc14.windows.zip' -OutFile 'embree64.zip' +# Seems like TBB dropped Windows 8.1 support in version 2020 so we'll use older versions +Invoke-WebRequest 'https://github.com/embree/embree/releases/download/v3.9.0/embree-3.9.0.x64.vc14.windows.zip' -OutFile 'embree64.zip' 7z x embree64.zip -oc:\ -Invoke-WebRequest 'https://github.com/oneapi-src/oneTBB/releases/download/v2020.2/tbb-2020.2-win.zip' -OutFile 'tbb.zip' +Invoke-WebRequest 'https://github.com/oneapi-src/oneTBB/releases/download/2019_U9/tbb2019_20191006oss_win.zip' -OutFile 'tbb.zip' 7z x tbb.zip -oc:\ git submodule update --init --recursive @@ -20,7 +21,7 @@ choco install ninja mkdir build-windows cd build-windows -cmake .. -GNinja -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_BUILD_TYPE=Release +cmake .. -GNinja -Dembree_DIR="C:\embree-3.9.0.x64.vc14.windows" -DTBB_DIR="C:\tbb2019_20191006oss\cmake" -DCMAKE_BUILD_TYPE=Release -DLEGACY_EMBREE=YES ninja if ( $? -eq $false ) { diff --git a/light/CMakeLists.txt b/light/CMakeLists.txt index 6615a83e..3211505b 100644 --- a/light/CMakeLists.txt +++ b/light/CMakeLists.txt @@ -45,7 +45,12 @@ add_executable(light main.cc) target_link_libraries(light PRIVATE common liblight) if (embree_FOUND) - target_link_libraries (liblight PRIVATE embree) + if (LEGACY_EMBREE) + target_link_libraries (liblight PRIVATE ${EMBREE_LIBRARY}) + else() + target_link_libraries (liblight PRIVATE embree) + endif() + add_definitions(-DHAVE_EMBREE) # macOS/homebrew: hack around find_file applying the .. before resolving the symlink @@ -74,11 +79,19 @@ if (embree_FOUND) endif() add_custom_command(TARGET light POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" ) + if (LEGACY_EMBREE) + add_custom_command(TARGET light POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${embree_DIR}/bin/embree3.dll" "$") + else() + add_custom_command(TARGET light POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$") + endif() + + if (NOT EMBREE_LICENSE STREQUAL EMBREE_LICENSE-NOTFOUND) add_custom_command(TARGET light POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${EMBREE_LICENSE}" "$/LICENSE-embree.txt") @@ -94,7 +107,11 @@ if (embree_FOUND) COMMAND bash ARGS -c \"install_name_tool -add_rpath @loader_path $ || true\") endif() - install(FILES $ DESTINATION bin) + if (LEGACY_EMBREE) + install(FILES "${embree_DIR}/bin/embree3.dll" DESTINATION bin) + else() + install(FILES $ DESTINATION bin) + endif() # install TBB if(UNIX) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 14c453da..4295925a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,10 +33,18 @@ target_compile_definitions(tests PRIVATE DOCTEST_CONFIG_SUPER_FAST_ASSERTS) # HACK: copy .dll dependencies add_custom_command(TARGET tests POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" ) + +if (LEGACY_EMBREE) + add_custom_command(TARGET tests POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${embree_DIR}/bin/embree3.dll" "$") +else() + add_custom_command(TARGET tests POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$") +endif() + if (NOT EMBREE_TBB_DLL STREQUAL EMBREE_TBB_DLL-NOTFOUND) add_custom_command(TARGET tests POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${EMBREE_TBB_DLL}" "$") From 99e5f15d42b2c76a78bb7b9308a18fd7d47a74ea Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 13 Nov 2022 16:52:14 -0700 Subject: [PATCH 16/23] Revert "ci: use older embree/tbb which support Win8.1" This reverts commit 50c4709d3158756835666e050e6eeb9d989a23ff. --- .gitignore | 2 +- appveyor.yml | 5 +++++ build-appveyor.ps1 | 9 +-------- build-windows.ps1 | 7 +++---- light/CMakeLists.txt | 23 +++-------------------- tests/CMakeLists.txt | 10 +--------- 6 files changed, 14 insertions(+), 42 deletions(-) diff --git a/.gitignore b/.gitignore index 30bb64c0..bd4afd64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ bin/ cmakebuild/ cmake-*/ -*build*/ +build*/ CMakeFiles/ *.xcodeproj .vscode/** diff --git a/appveyor.yml b/appveyor.yml index 48a06e6d..b181162b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,6 +4,11 @@ platform: - x64 version: 1.0.{build} +install: +- ps: Invoke-WebRequest 'https://github.com/embree/embree/releases/download/v3.12.1/embree-3.12.1.x64.vc14.windows.zip' -OutFile 'embree64.zip' +- ps: 7z x embree64.zip -oc:\ +- ps: Invoke-WebRequest 'https://github.com/oneapi-src/oneTBB/releases/download/v2020.2/tbb-2020.2-win.zip' -OutFile 'tbb.zip' +- ps: 7z x tbb.zip -oc:\ build_script: - cmd: powershell .\build-appveyor.ps1 artifacts: diff --git a/build-appveyor.ps1 b/build-appveyor.ps1 index f87c4e88..b76e1b7d 100644 --- a/build-appveyor.ps1 +++ b/build-appveyor.ps1 @@ -1,10 +1,3 @@ -# Download embree and tbb -# Seems like TBB dropped Windows 8.1 support in version 2020 so we'll use older versions -Invoke-WebRequest 'https://github.com/embree/embree/releases/download/v3.9.0/embree-3.9.0.x64.vc14.windows.zip' -OutFile 'embree64.zip' -7z x embree64.zip -oc:\ -Invoke-WebRequest 'https://github.com/oneapi-src/oneTBB/releases/download/2019_U9/tbb2019_20191006oss_win.zip' -OutFile 'tbb.zip' -7z x tbb.zip -oc:\ - git submodule update --init --recursive $env:Path += ";C:\cygwin64\bin" @@ -25,7 +18,7 @@ mkdir cmakebuild cd cmakebuild -cmake .. -T v143 -Dembree_DIR="C:\embree-3.9.0.x64.vc14.windows" -DTBB_DIR="C:\tbb2019_20191006oss\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DLEGACY_EMBREE=YES +cmake .. -T v143 -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_GENERATOR_PLATFORM=x64 -DENABLE_LIGHTPREVIEW=NO -DQt5Widgets_DIR="C:\Qt\5.8\msvc2013_64\lib\cmake\Qt5Widgets" $cmakePlatform = "x64" diff --git a/build-windows.ps1 b/build-windows.ps1 index 0df041fa..ecc6d24b 100644 --- a/build-windows.ps1 +++ b/build-windows.ps1 @@ -1,8 +1,7 @@ # Download embree and tbb -# Seems like TBB dropped Windows 8.1 support in version 2020 so we'll use older versions -Invoke-WebRequest 'https://github.com/embree/embree/releases/download/v3.9.0/embree-3.9.0.x64.vc14.windows.zip' -OutFile 'embree64.zip' +Invoke-WebRequest 'https://github.com/embree/embree/releases/download/v3.12.1/embree-3.12.1.x64.vc14.windows.zip' -OutFile 'embree64.zip' 7z x embree64.zip -oc:\ -Invoke-WebRequest 'https://github.com/oneapi-src/oneTBB/releases/download/2019_U9/tbb2019_20191006oss_win.zip' -OutFile 'tbb.zip' +Invoke-WebRequest 'https://github.com/oneapi-src/oneTBB/releases/download/v2020.2/tbb-2020.2-win.zip' -OutFile 'tbb.zip' 7z x tbb.zip -oc:\ git submodule update --init --recursive @@ -21,7 +20,7 @@ choco install ninja mkdir build-windows cd build-windows -cmake .. -GNinja -Dembree_DIR="C:\embree-3.9.0.x64.vc14.windows" -DTBB_DIR="C:\tbb2019_20191006oss\cmake" -DCMAKE_BUILD_TYPE=Release -DLEGACY_EMBREE=YES +cmake .. -GNinja -Dembree_DIR="C:\embree-3.12.1.x64.vc14.windows" -DTBB_DIR="C:\tbb\cmake" -DCMAKE_BUILD_TYPE=Release ninja if ( $? -eq $false ) { diff --git a/light/CMakeLists.txt b/light/CMakeLists.txt index 3211505b..6615a83e 100644 --- a/light/CMakeLists.txt +++ b/light/CMakeLists.txt @@ -45,12 +45,7 @@ add_executable(light main.cc) target_link_libraries(light PRIVATE common liblight) if (embree_FOUND) - if (LEGACY_EMBREE) - target_link_libraries (liblight PRIVATE ${EMBREE_LIBRARY}) - else() - target_link_libraries (liblight PRIVATE embree) - endif() - + target_link_libraries (liblight PRIVATE embree) add_definitions(-DHAVE_EMBREE) # macOS/homebrew: hack around find_file applying the .. before resolving the symlink @@ -79,19 +74,11 @@ if (embree_FOUND) endif() add_custom_command(TARGET light POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" ) - if (LEGACY_EMBREE) - add_custom_command(TARGET light POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different "${embree_DIR}/bin/embree3.dll" "$") - else() - add_custom_command(TARGET light POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$") - endif() - - if (NOT EMBREE_LICENSE STREQUAL EMBREE_LICENSE-NOTFOUND) add_custom_command(TARGET light POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${EMBREE_LICENSE}" "$/LICENSE-embree.txt") @@ -107,11 +94,7 @@ if (embree_FOUND) COMMAND bash ARGS -c \"install_name_tool -add_rpath @loader_path $ || true\") endif() - if (LEGACY_EMBREE) - install(FILES "${embree_DIR}/bin/embree3.dll" DESTINATION bin) - else() - install(FILES $ DESTINATION bin) - endif() + install(FILES $ DESTINATION bin) # install TBB if(UNIX) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4295925a..14c453da 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -33,18 +33,10 @@ target_compile_definitions(tests PRIVATE DOCTEST_CONFIG_SUPER_FAST_ASSERTS) # HACK: copy .dll dependencies add_custom_command(TARGET tests POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$" ) - -if (LEGACY_EMBREE) - add_custom_command(TARGET tests POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different "${embree_DIR}/bin/embree3.dll" "$") -else() - add_custom_command(TARGET tests POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$") -endif() - if (NOT EMBREE_TBB_DLL STREQUAL EMBREE_TBB_DLL-NOTFOUND) add_custom_command(TARGET tests POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${EMBREE_TBB_DLL}" "$") From 37b901a915d4cf70e2686e051312139f8fb0e214 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 13 Nov 2022 17:58:25 -0700 Subject: [PATCH 17/23] fmtlib 7.1.3 -> 9.1.0 --- 3rdparty/fmt | 2 +- include/common/aabb.hh | 10 +++++----- include/common/bspfile.hh | 8 ++++---- include/common/fs.hh | 2 +- include/common/log.hh | 8 ++++---- include/common/parser.hh | 6 +++--- include/common/qvec.hh | 20 ++++++++++---------- include/common/settings.hh | 1 + include/qbsp/qbsp.hh | 6 +++--- 9 files changed, 32 insertions(+), 31 deletions(-) diff --git a/3rdparty/fmt b/3rdparty/fmt index 7bdf0628..a3370119 160000 --- a/3rdparty/fmt +++ b/3rdparty/fmt @@ -1 +1 @@ -Subproject commit 7bdf0628b1276379886c7f6dda2cef2b3b374f0b +Subproject commit a33701196adfad74917046096bf5a2aa0ab0bb50 diff --git a/include/common/aabb.hh b/include/common/aabb.hh index 3aa29883..c9938036 100644 --- a/include/common/aabb.hh +++ b/include/common/aabb.hh @@ -224,11 +224,11 @@ struct fmt::formatter> : formatter> template auto format(const aabb &b, FormatContext &ctx) -> decltype(ctx.out()) { - format_to(ctx.out(), "{{mins: "); - formatter>::format(b.mins(), ctx); - format_to(ctx.out(), ", maxs: "); - formatter>::format(b.maxs(), ctx); - format_to(ctx.out(), "}}"); + fmt::format_to(ctx.out(), "{{mins: "); + fmt::formatter>::format(b.mins(), ctx); + fmt::format_to(ctx.out(), ", maxs: "); + fmt::formatter>::format(b.maxs(), ctx); + fmt::format_to(ctx.out(), "}}"); return ctx.out(); } }; diff --git a/include/common/bspfile.hh b/include/common/bspfile.hh index 86645554..12107bcb 100644 --- a/include/common/bspfile.hh +++ b/include/common/bspfile.hh @@ -355,18 +355,18 @@ struct fmt::formatter auto format(const bspversion_t &v, FormatContext &ctx) -> decltype(ctx.out()) { if (v.name) { - format_to(ctx.out(), "{} ", v.name); + fmt::format_to(ctx.out(), "{} ", v.name); } // Q2-esque BSPs are printed as, ex, IBSP:38 if (v.version.has_value()) { char ident[5] = {(char)(v.ident & 0xFF), (char)((v.ident >> 8) & 0xFF), (char)((v.ident >> 16) & 0xFF), (char)((v.ident >> 24) & 0xFF), '\0'}; - return format_to(ctx.out(), "{}:{}", ident, v.version.value()); + return fmt::format_to(ctx.out(), "{}:{}", ident, v.version.value()); } // Q1-esque BSPs are printed as, ex, bsp29 - return format_to(ctx.out(), "{}", v.short_name); + return fmt::format_to(ctx.out(), "{}", v.short_name); } }; @@ -410,7 +410,7 @@ struct texvec : qmat // Fmt support template -struct fmt::formatter> : formatter> +struct fmt::formatter> : fmt::formatter> { }; diff --git a/include/common/fs.hh b/include/common/fs.hh index 8fb78f51..f0bbf34a 100644 --- a/include/common/fs.hh +++ b/include/common/fs.hh @@ -113,6 +113,6 @@ struct fmt::formatter template auto format(const fs::path &p, FormatContext &ctx) { - return format_to(ctx.out(), "{}", p.string()); + return fmt::format_to(ctx.out(), "{}", p.string()); } }; diff --git a/include/common/log.hh b/include/common/log.hh index 491242a2..295e221b 100644 --- a/include/common/log.hh +++ b/include/common/log.hh @@ -74,15 +74,15 @@ template inline void print(flag type, const char *fmt, const Args &...args) { if (mask & type) { - print(type, fmt::format(fmt, std::forward(args)...).c_str()); + print(type, fmt::format(fmt::runtime(fmt), std::forward(args)...).c_str()); } } // format print to default targets template -inline void print(const char *fmt, const Args &...args) +inline void print(const char *formt, const Args &...args) { - print(flag::DEFAULT, fmt::format(fmt, std::forward(args)...).c_str()); + print(flag::DEFAULT, fmt::format(fmt::runtime(formt), std::forward(args)...).c_str()); } void header(const char *name); @@ -182,7 +182,7 @@ struct stat_tracker_t template [[noreturn]] inline void Error(const char *fmt, const Args &...args) { - auto formatted = fmt::format(fmt, std::forward(args)...); + auto formatted = fmt::format(fmt::runtime(fmt), std::forward(args)...); Error(formatted.c_str()); } diff --git a/include/common/parser.hh b/include/common/parser.hh index 13b332e3..02ab5f4a 100644 --- a/include/common/parser.hh +++ b/include/common/parser.hh @@ -93,13 +93,13 @@ struct fmt::formatter auto format(const parser_source_location &v, FormatContext &ctx) -> decltype(ctx.out()) { if (v.source_name) { - format_to(ctx.out(), "{}", *v.source_name.get()); + fmt::format_to(ctx.out(), "{}", *v.source_name.get()); } else { - format_to(ctx.out(), "unknown/unset location"); + fmt::format_to(ctx.out(), "unknown/unset location"); } if (v.line_number.has_value()) { - format_to(ctx.out(), "[line {}]", v.line_number.value()); + fmt::format_to(ctx.out(), "[line {}]", v.line_number.value()); } return ctx.out(); diff --git a/include/common/qvec.hh b/include/common/qvec.hh index 55c5c7a1..f522fd1f 100644 --- a/include/common/qvec.hh +++ b/include/common/qvec.hh @@ -341,11 +341,11 @@ struct fmt::formatter> auto format(const qvec &p, FormatContext &ctx) -> decltype(ctx.out()) { for (size_t i = 0; i < N - 1; i++) { - format_to(ctx.out(), "{}", p[i]); - format_to(ctx.out(), " "); + fmt::format_to(ctx.out(), "{}", p[i]); + fmt::format_to(ctx.out(), " "); } - return format_to(ctx.out(), "{}", p[N - 1]); + return fmt::format_to(ctx.out(), "{}", p[N - 1]); } }; @@ -838,9 +838,9 @@ struct fmt::formatter> : formatter> template auto format(const qplane3 &p, FormatContext &ctx) -> decltype(ctx.out()) { - format_to(ctx.out(), "{{normal: "); - formatter>::format(p.normal, ctx); - format_to(ctx.out(), ", dist: {}}}", p.dist); + fmt::format_to(ctx.out(), "{{normal: "); + fmt::formatter>::format(p.normal, ctx); + fmt::format_to(ctx.out(), ", dist: {}}}", p.dist); return ctx.out(); } }; @@ -1026,12 +1026,12 @@ struct fmt::formatter> : formatter> auto format(const qmat &p, FormatContext &ctx) -> decltype(ctx.out()) { for (size_t i = 0; i < NRow; i++) { - format_to(ctx.out(), "[ "); - formatter>::format(p.row(i), ctx); - format_to(ctx.out(), " ]"); + fmt::format_to(ctx.out(), "[ "); + fmt::formatter>::format(p.row(i), ctx); + fmt::format_to(ctx.out(), " ]"); if (i != NRow - 1) { - format_to(ctx.out(), "\n"); + fmt::format_to(ctx.out(), "\n"); } } diff --git a/include/common/settings.hh b/include/common/settings.hh index a92125fb..89deb097 100644 --- a/include/common/settings.hh +++ b/include/common/settings.hh @@ -34,6 +34,7 @@ #include #include #include +#include namespace settings { diff --git a/include/qbsp/qbsp.hh b/include/qbsp/qbsp.hh index c6dfb87b..a8146475 100644 --- a/include/qbsp/qbsp.hh +++ b/include/qbsp/qbsp.hh @@ -368,9 +368,9 @@ struct fmt::formatter : formatter template auto format(const qbsp_plane_t &p, FormatContext &ctx) -> decltype(ctx.out()) { - format_to(ctx.out(), "<"); - formatter::format(p.get_plane(), ctx); - format_to(ctx.out(), ", type: {}>", p.get_type()); + fmt::format_to(ctx.out(), "<"); + fmt::formatter::format(p.get_plane(), ctx); + fmt::format_to(ctx.out(), ", type: {}>", p.get_type()); return ctx.out(); } }; From 629f86625ede996a7a12929bfa3e4cc5916dbf44 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Sun, 13 Nov 2022 18:58:08 -0700 Subject: [PATCH 18/23] log.cc: use fmt::group_digits to avoid locale manipulation this is to get thousands separators, e.g. 10000 prints as 10,000 the `auto old = std::locale::global(std::locale("en_US.UTF-8"));` line was throwing on Win8.1 --- common/log.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/common/log.cc b/common/log.cc index 9073d6f5..00369fb8 100644 --- a/common/log.cc +++ b/common/log.cc @@ -304,16 +304,14 @@ void stat_tracker_t::print_stats() stats_printed = true; - auto old = std::locale::global(std::locale("en_US.UTF-8")); // add 8 char padding just to keep it away from the left side size_t number_padding = number_of_digit_padding() + 4; for (auto &stat : stats) { if (stat.show_even_if_zero || stat.count) { - print(flag::STAT, "{}{:{}L} {}\n", stat.is_warning ? "WARNING: " : "", stat.count, stat.is_warning ? 0 : number_padding, stat.name); + print(flag::STAT, "{}{:{}} {}\n", stat.is_warning ? "WARNING: " : "", fmt::group_digits(stat.count.load()), stat.is_warning ? 0 : number_padding, stat.name); } } - std::locale::global(old); } stat_tracker_t::~stat_tracker_t() From c6b19fe6daaf7f58323b30d5b44e8bfa7bdef149 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Mon, 14 Nov 2022 00:30:37 -0700 Subject: [PATCH 19/23] light: implement -novanilla with -world_units_per_luxel currently it's required because the non-novanilla path isn't yet implemented --- light/ltface.cc | 10 ++++++---- tests/test_ltface.cc | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/light/ltface.cc b/light/ltface.cc index 13cc6e1e..708055c9 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -2848,13 +2848,15 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, lightofs = out - filebase.data(); } - if (facesup) { + if (facesup_decoupled && light_options.novanilla.value()) { + facesup_decoupled->offset = lightofs; + face->lightofs = -1; + } else if (facesup_decoupled && !light_options.novanilla.value()) { + FError("-world_units_per_luxel currently requires -novanilla"); + } else if (facesup) { facesup->lightofs = lightofs; } else { face->lightofs = lightofs; - if (facesup_decoupled) { - facesup_decoupled->offset = lightofs; - } } // sanity check that we don't save a lightmap for a non-lightmapped face diff --git a/tests/test_ltface.cc b/tests/test_ltface.cc index fee69fd4..8309fccd 100644 --- a/tests/test_ltface.cc +++ b/tests/test_ltface.cc @@ -64,7 +64,7 @@ static testresults_t LoadTestmap(const std::filesystem::path &name, std::vector< } TEST_CASE("TestLight") { - LoadTestmap("q2_lightmap_custom_scale.map", {"-threads", "1", "-world_units_per_luxel", "8"}); + LoadTestmap("q2_lightmap_custom_scale.map", {"-threads", "1", "-world_units_per_luxel", "8", "-novanilla"}); } TEST_CASE("emissive cube artifacts") { @@ -80,7 +80,7 @@ TEST_CASE("emissive cube artifacts") { // // "_surflight_rescale" "0" // - auto [bsp, bspx] = LoadTestmap("light_q2_emissive_cube.map", {"-threads", "1", "-world_units_per_luxel", "4"}); + auto [bsp, bspx] = LoadTestmap("light_q2_emissive_cube.map", {"-threads", "1", "-world_units_per_luxel", "4", "-novanilla"}); const auto start = qvec3d{1044, -1244, 880}; const auto end = qvec3d{1044, -1272, 880}; @@ -107,3 +107,43 @@ TEST_CASE("emissive cube artifacts") { previous_sample = sample; } } + +TEST_CASE("-novanilla + -world_units_per_luxel") +{ + auto [bsp, bspx] = LoadTestmap("q2_lightmap_custom_scale.map", {"-novanilla", "-world_units_per_luxel", "8"}); + + for (auto &face : bsp.dfaces) { + CHECK(face.lightofs == -1); + } + + // make sure no other bspx lumps are written + CHECK(bspx.size() == 1); + CHECK(bspx.find("DECOUPLED_LM") != bspx.end()); + + // make sure all dlightdata bytes are accounted for by the DECOUPLED_LM lump + // and no extra was written. + size_t expected_dlightdata_bytes = 0; + for (auto &face : bsp.dfaces) { + // count used styles + size_t face_used_styles = 0; + for (auto style : face.styles) { + if (style != 255) { + ++face_used_styles; + } + } + + // count used pixels per style + auto lm_info = BSPX_DecoupledLM(bspx, Face_GetNum(&bsp, &face)); + const faceextents_t extents(face, bsp, lm_info.lmwidth, lm_info.lmheight, lm_info.world_to_lm_space); + int samples_per_face = extents.numsamples() * face_used_styles; + + // round up to multiple of 4 + if (samples_per_face % 4) { + samples_per_face += (4 - (samples_per_face % 4)); + } + + int bytes_per_face = 3 * samples_per_face; + expected_dlightdata_bytes += bytes_per_face; + } + CHECK(bsp.dlightdata.size() == expected_dlightdata_bytes); +} From 959fe32e18b843eaca9d9beaa8e4fcfb7606e9c0 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Mon, 14 Nov 2022 21:49:01 -0700 Subject: [PATCH 20/23] portals.cc: add -verbose logging for missing portal sides --- qbsp/portals.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qbsp/portals.cc b/qbsp/portals.cc index 98727fd5..9c44ada1 100644 --- a/qbsp/portals.cc +++ b/qbsp/portals.cc @@ -770,7 +770,7 @@ void EmitAreaPortals(node_t *headnode) struct visible_faces_stats_t : logging::stat_tracker_t { - stat &sides_not_found = register_stat("sides not found", false, true); + stat &sides_not_found = register_stat("sides not found (use -verbose to display)", false, true); stat &sides_visible = register_stat("sides visible"); }; @@ -870,6 +870,7 @@ static void FindPortalSide(portal_t *p, visible_faces_stats_t &stats) if (!bestside[0] && !bestside[1]) { stats.sides_not_found++; + logging::print(logging::flag::VERBOSE, "couldn't find portal side at {}\n", p->winding.center()); } p->sidefound = true; From 46d460277a3dca4858090f2222476dca2b80db73 Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Mon, 14 Nov 2022 23:58:31 -0700 Subject: [PATCH 21/23] ltface: support -world_units_per_luxel without -novanilla first pass implementation - quality of vanilla LM is bad, due to nearest sampling the decoupled lightmap --- light/ltface.cc | 83 ++++++++++++++++++++++++++- testmaps/q2_lightmap_custom_scale.map | 7 +++ tests/test_ltface.cc | 4 +- 3 files changed, 89 insertions(+), 5 deletions(-) diff --git a/light/ltface.cc b/light/ltface.cc index 708055c9..b89772c7 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -2656,6 +2656,54 @@ static void WriteSingleLightmap(const mbsp_t *bsp, const mface_t *face, const li } } +/** + * - Writes (output_width * output_height) bytes to `out` + * - Writes (output_width * output_height * 3) bytes to `lit` + * - Writes (output_width * output_height * 3) bytes to `lux` + */ +static void WriteSingleLightmap_FromDecoupled(const mbsp_t *bsp, const mface_t *face, const lightsurf_t *lightsurf, + const lightmap_t *lm, const int output_width, const int output_height, uint8_t *out, uint8_t *lit, uint8_t *lux) +{ + // this is the lightmap data in the "decoupled" coordinate system + std::vector fullres = LightmapColorsToGLMVector(lightsurf, lm); + + for (int t = 0; t < output_height; t++) { + for (int s = 0; s < output_width; s++) { + // convert from vanilla lm coord to decoupled lm coord + qvec3f world = lightsurf->vanilla_extents.LMCoordToWorld(qvec2f(s, t)); + qvec2f decoupled_lm_coord = lightsurf->extents.worldToLMCoord(world); + + decoupled_lm_coord = decoupled_lm_coord * light_options.extra.value(); + + const int input_sample_s = clamp((int)decoupled_lm_coord[0], 0, lightsurf->width - 1); + const int input_sample_t = clamp((int)decoupled_lm_coord[1], 0, lightsurf->height - 1); + const int sampleindex = (input_sample_t * lightsurf->width) + input_sample_s; + + if (lit || out) { + const qvec4f &color = fullres.at(sampleindex); + + if (lit) { + *lit++ = color[0]; + *lit++ = color[1]; + *lit++ = color[2]; + } + + if (out) { + // FIXME: implement + *out++ = 0; + } + } + + if (lux) { + // FIXME: implement + *lux++ = 0; + *lux++ = 0; + *lux++ = 0; + } + } + } +} + void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, bspx_decoupled_lm_perface *facesup_decoupled, lightsurf_t *lightsurf, const faceextents_t &extents, const faceextents_t &output_extents) @@ -2848,11 +2896,9 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, lightofs = out - filebase.data(); } - if (facesup_decoupled && light_options.novanilla.value()) { + if (facesup_decoupled) { facesup_decoupled->offset = lightofs; face->lightofs = -1; - } else if (facesup_decoupled && !light_options.novanilla.value()) { - FError("-world_units_per_luxel currently requires -novanilla"); } else if (facesup) { facesup->lightofs = lightofs; } else { @@ -2882,6 +2928,37 @@ void SaveLightmapSurface(const mbsp_t *bsp, mface_t *face, facesup_t *facesup, lux += (size * 3); } } + + // write vanilla lightmap if -world_units_per_luxel is in use but not -novanilla + if (facesup_decoupled && !light_options.novanilla.value()) { + // FIXME: duplicates some code from above + GetFileSpace(&out, &lit, &lux, lightsurf->vanilla_extents.numsamples() * numstyles); + + // Q2/HL native colored lightmaps + if (bsp->loadversion->game->has_rgb_lightmap) { + lightofs = lit - lit_filebase.data(); + } else { + lightofs = out - filebase.data(); + } + face->lightofs = lightofs; + + for (int mapnum = 0; mapnum < numstyles; mapnum++) { + const lightmap_t *lm = sorted.at(mapnum); + + WriteSingleLightmap_FromDecoupled(bsp, face, lightsurf, lm, lightsurf->vanilla_extents.width(), + lightsurf->vanilla_extents.height(), out, lit, lux); + + if (out) { + out += lightsurf->vanilla_extents.numsamples(); + } + if (lit) { + lit += (lightsurf->vanilla_extents.numsamples() * 3); + } + if (lux) { + lux += (lightsurf->vanilla_extents.numsamples() * 3); + } + } + } } std::unique_ptr CreateLightmapSurface(const mbsp_t *bsp, const mface_t *face, const facesup_t *facesup, diff --git a/testmaps/q2_lightmap_custom_scale.map b/testmaps/q2_lightmap_custom_scale.map index 6ce8e512..91d70052 100644 --- a/testmaps/q2_lightmap_custom_scale.map +++ b/testmaps/q2_lightmap_custom_scale.map @@ -977,3 +977,10 @@ "origin" "-398 -160 94" "light" "1200" } +// entity 7 +{ +"classname" "light" +"origin" "232 -248 104" +"style" "1" +"_color" "183 255 227" +} diff --git a/tests/test_ltface.cc b/tests/test_ltface.cc index 8309fccd..2ef5aba9 100644 --- a/tests/test_ltface.cc +++ b/tests/test_ltface.cc @@ -63,8 +63,8 @@ static testresults_t LoadTestmap(const std::filesystem::path &name, std::vector< } } -TEST_CASE("TestLight") { - LoadTestmap("q2_lightmap_custom_scale.map", {"-threads", "1", "-world_units_per_luxel", "8", "-novanilla"}); +TEST_CASE("-world_units_per_luxel") { + LoadTestmap("q2_lightmap_custom_scale.map", {"-world_units_per_luxel", "8"}); } TEST_CASE("emissive cube artifacts") { From eb3dfe795218187843f6ae14918a155d9950a8fb Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Tue, 15 Nov 2022 00:50:11 -0700 Subject: [PATCH 22/23] ltface: use bilinear interpolation in WriteSingleLightmap_FromDecoupled --- light/ltface.cc | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/light/ltface.cc b/light/ltface.cc index b89772c7..41f67bfc 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -2667,21 +2667,47 @@ static void WriteSingleLightmap_FromDecoupled(const mbsp_t *bsp, const mface_t * // this is the lightmap data in the "decoupled" coordinate system std::vector fullres = LightmapColorsToGLMVector(lightsurf, lm); + // maps a luxel in the vanilla lightmap to the corresponding position in the decoupled lightmap + const qmat4x4f vanillaLMToDecoupled = lightsurf->extents.worldToLMMatrix * lightsurf->vanilla_extents.lmToWorldMatrix; + + // samples the "decoupled" lightmap at an integer coordinate, with clamping + auto tex = [&lightsurf, &fullres](int x, int y) -> qvec4f { + const int x_clamped = clamp(x, 0, lightsurf->width - 1); + const int y_clamped = clamp(y, 0, lightsurf->height - 1); + + const int sampleindex = (y_clamped * lightsurf->width) + x_clamped; + assert(sampleindex >= 0); + assert(sampleindex < fullres.size()); + + return fullres[sampleindex]; + }; + for (int t = 0; t < output_height; t++) { for (int s = 0; s < output_width; s++) { // convert from vanilla lm coord to decoupled lm coord - qvec3f world = lightsurf->vanilla_extents.LMCoordToWorld(qvec2f(s, t)); - qvec2f decoupled_lm_coord = lightsurf->extents.worldToLMCoord(world); + qvec2f decoupled_lm_coord = vanillaLMToDecoupled * qvec4f(s, t, 0, 1); decoupled_lm_coord = decoupled_lm_coord * light_options.extra.value(); - const int input_sample_s = clamp((int)decoupled_lm_coord[0], 0, lightsurf->width - 1); - const int input_sample_t = clamp((int)decoupled_lm_coord[1], 0, lightsurf->height - 1); - const int sampleindex = (input_sample_t * lightsurf->width) + input_sample_s; + // split into integer/fractional part for bilinear interpolation + const int coord_floor_x = (int)decoupled_lm_coord[0]; + const int coord_floor_y = (int)decoupled_lm_coord[1]; + + const float coord_frac_x = decoupled_lm_coord[0] - coord_floor_x; + const float coord_frac_y = decoupled_lm_coord[1] - coord_floor_y; + + // 2D bilinear interpolation + const qvec4f color = + mix( + mix(tex(coord_floor_x, coord_floor_y), + tex(coord_floor_x + 1, coord_floor_y), + coord_frac_x), + mix(tex(coord_floor_x, coord_floor_y + 1), + tex(coord_floor_x + 1, coord_floor_y + 1), + coord_frac_x), + coord_frac_y); if (lit || out) { - const qvec4f &color = fullres.at(sampleindex); - if (lit) { *lit++ = color[0]; *lit++ = color[1]; From 4c218f5e91a566d2ffb96e1319d3d08132c174ae Mon Sep 17 00:00:00 2001 From: Eric Wasylishen Date: Tue, 15 Nov 2022 23:52:34 -0700 Subject: [PATCH 23/23] common: factor out LMSCALE_DEFAULT = 16.0; --- common/bspinfo.cc | 2 +- include/common/bsputils.hh | 2 ++ light/light.cc | 4 ++-- light/ltface.cc | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/common/bspinfo.cc b/common/bspinfo.cc index a1088a10..a0888e6b 100644 --- a/common/bspinfo.cc +++ b/common/bspinfo.cc @@ -228,7 +228,7 @@ static faceextents_t get_face_extents(const mbsp_t &bsp, const bspxentries_t &bs return {face, bsp, bspx.lmwidth, bspx.lmheight, bspx.world_to_lm_space}; } if (!use_bspx) { - return {face, bsp, 16.0}; + return {face, bsp, LMSCALE_DEFAULT}; } return {face, bsp, diff --git a/include/common/bsputils.hh b/include/common/bsputils.hh index f28876e7..2a6f37b5 100644 --- a/include/common/bsputils.hh +++ b/include/common/bsputils.hh @@ -125,6 +125,8 @@ constexpr size_t MAXDIMENSION = 255 + 1; struct world_units_per_luxel_t {}; +constexpr float LMSCALE_DEFAULT = 16.0f; + class faceextents_t { public: diff --git a/light/light.cc b/light/light.cc index f1adeb96..098c54f6 100644 --- a/light/light.cc +++ b/light/light.cc @@ -714,10 +714,10 @@ static void FindModelInfo(const mbsp_t *bsp) float lightmapscale = WorldEnt().get_int("_lightmap_scale"); if (!lightmapscale) - lightmapscale = 16; /* the default */ + lightmapscale = LMSCALE_DEFAULT; /* the default */ if (lightmapscale <= 0) FError("lightmap scale is 0 or negative\n"); - if (light_options.lightmap_scale.isChanged() || lightmapscale != 16) + if (light_options.lightmap_scale.isChanged() || lightmapscale != LMSCALE_DEFAULT) logging::print("Forcing lightmap scale of {}qu\n", lightmapscale); /*I'm going to do this check in the hopes that there's a benefit to cheaper scaling in engines (especially software * ones that might be able to just do some mip hacks). This tool doesn't really care.*/ diff --git a/light/ltface.cc b/light/ltface.cc index 41f67bfc..1295e48f 100644 --- a/light/ltface.cc +++ b/light/ltface.cc @@ -703,7 +703,7 @@ static std::unique_ptr Lightsurf_Init(const modelinfo_t *modelinfo, } else { lightsurf->extents = faceextents_t(*face, *bsp, lightsurf->lightmapscale); } - lightsurf->vanilla_extents = faceextents_t(*face, *bsp, 16.0); + lightsurf->vanilla_extents = faceextents_t(*face, *bsp, LMSCALE_DEFAULT); CalcPoints(modelinfo, modelinfo->offset, lightsurf.get(), bsp, face);