From 07cd3b3769f4541890d622615580c32cafd0bf3d Mon Sep 17 00:00:00 2001 From: maj00r Date: Mon, 14 Sep 2026 16:35:06 +0200 Subject: [PATCH] Editor imagery: unflip the WMS tiles, and build without libcurl Two things about the map behind the plan, neither of them the plan's own doing. stb keeps one flip flag for the whole program - there is a single stb_image.c in the build - and the model texture loader turned it on for its own sake, because models want the bottom row first. A WMS tile is the other way about: its first row is its northern edge, which is what the drawing code takes v=0 to be. So every tile came out upside down as soon as any model texture had been loaded through that path, which is why this has come and gone with the order things load in. Both decoders now say which way they want it per thread, where nobody else can reach it. And libcurl is no longer required to configure. A tree without it builds an editor that draws and exports as usual, only with nothing behind the plan, and says so once rather than showing a silent grey screen; the CI installs it, so what comes out of the build has its imagery. --- .github/workflows/build.yml | 2 +- .github/workflows/build_bin.yml | 1 + CMakeLists.txt | 14 ++++++++++--- editor/orthophoto.cpp | 37 +++++++++++++++++++++++++++++++-- model/Texture.cpp | 5 ++++- 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b64895f3..c56b1585 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -40,7 +40,7 @@ jobs: build-essential ninja-build wget lsb-release software-properties-common gnupg \ libgl1-mesa-dev libglew-dev libglfw3-dev \ libpng-dev libopenal-dev libluajit-5.1-dev \ - libserialport-dev libsndfile1-dev \ + libserialport-dev libsndfile1-dev libcurl4-openssl-dev \ xorg-dev libxkbcommon-dev libwayland-dev wayland-protocols - name: Install LLVM/Clang 22 diff --git a/.github/workflows/build_bin.yml b/.github/workflows/build_bin.yml index c64539b5..6ba1a384 100644 --- a/.github/workflows/build_bin.yml +++ b/.github/workflows/build_bin.yml @@ -181,6 +181,7 @@ jobs: libluajit-5.1-dev \ libserialport-dev \ libsndfile1-dev \ + libcurl4-openssl-dev \ xorg-dev \ libxkbcommon-dev \ libwayland-dev \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 3dc46bbd..7ec662cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -630,10 +630,18 @@ find_package(Threads REQUIRED) target_link_libraries(${PROJECT_NAME} Threads::Threads) # the editor's map imagery talks to a WMS over https. windows has WinHttp in the platform sdk; -# everywhere else libcurl is the transport (see editor/orthophoto.cpp) +# everywhere else libcurl is the transport (see editor/orthophoto.cpp). it is not required: a tree +# without it builds an editor that draws and exports as usual, only with no imagery behind the plan if (NOT WIN32) - find_package(CURL REQUIRED) - target_link_libraries(${PROJECT_NAME} CURL::libcurl) + find_package(CURL) + if (CURL_FOUND) + target_link_libraries(${PROJECT_NAME} CURL::libcurl) + target_compile_definitions(${PROJECT_NAME} PRIVATE WITH_CURL) + else() + message(WARNING + "libcurl not found: the editor will have no map imagery. " + "Install libcurl4-openssl-dev (Debian/Ubuntu) or libcurl-devel (Fedora) to get it back.") + endif() endif() find_package(GLM REQUIRED) diff --git a/editor/orthophoto.cpp b/editor/orthophoto.cpp index f4e650e2..3ba38771 100644 --- a/editor/orthophoto.cpp +++ b/editor/orthophoto.cpp @@ -20,7 +20,7 @@ module; #include #include #pragma comment(lib, "winhttp.lib") -#else +#elif defined(WITH_CURL) #include #endif @@ -37,6 +37,21 @@ obtain one at http://mozilla.org/MPL/2.0/. */ +namespace +{ + +// stb keeps one flip flag for the whole program - there is a single stb_image.c in the build - and +// the model texture loader turns it on for its own sake (models want the bottom row first). A WMS +// tile is the other way about: its first row is its northern edge, which is what the drawing code +// takes v=0 to be. So the orientation is stated per thread, where nobody else can reach it, rather +// than left to whoever decoded an image last +void decode_top_down() +{ + stbi_set_flip_vertically_on_load_thread(0); +} + +} // namespace + namespace editor { @@ -143,7 +158,7 @@ bool http_get(std::string const &Url, std::vector &Bytes, std::str return ok; } -#else +#elif defined(WITH_CURL) // libcurl's write callback: appends one chunk of the body to the caller's buffer std::size_t append_body(char const *Data, std::size_t const Size, std::size_t const Count, void *Userdata) @@ -205,6 +220,22 @@ bool http_get(std::string const &Url, std::vector &Bytes, std::str return ok; } +#else + +// built without a transport: libcurl was not there when this was configured. the editor draws and +// exports as usual - there is simply nothing to put behind the plan, and saying so once is better +// than a silent grey screen +bool http_get(std::string const &, std::vector &, std::string &Contenttype) +{ + Contenttype.clear(); + static auto const said = []() { + ErrorLog("Editor: built without libcurl, so there is no map imagery"); + return true; + }(); + (void)said; + return false; +} + #endif } // namespace @@ -375,6 +406,7 @@ unsigned int orthophoto_source::upload(editor::plan::TileKey const &Key) int width = 0; int height = 0; int channels = 0; + decode_top_down(); auto *pixels = stbi_load_from_memory(image->bytes.data(), static_cast(image->bytes.size()), &width, &height, &channels, 3); if (pixels == nullptr) { @@ -463,6 +495,7 @@ unsigned int upload_image(std::vector const &Bytes) int width = 0; int height = 0; int channels = 0; + decode_top_down(); auto *pixels = stbi_load_from_memory(Bytes.data(), static_cast(Bytes.size()), &width, &height, &channels, 3); if (pixels == nullptr) { diff --git a/model/Texture.cpp b/model/Texture.cpp index c7f65090..e95e6e8a 100644 --- a/model/Texture.cpp +++ b/model/Texture.cpp @@ -368,7 +368,10 @@ void opengl_texture::load_PNG() void opengl_texture::load_STBI() { int x, y, n; - stbi_set_flip_vertically_on_load(1); + // per thread, not for the whole program: there is one stb_image.c in the build, so the global + // flag reaches every other decoder too - which is how the editor's WMS tiles ended up upside + // down as soon as any model texture had been loaded through this path + stbi_set_flip_vertically_on_load_thread(1); uint8_t *image = stbi_load((name + type).c_str(), &x, &y, &n, 4); if (!image) {