From bcd7cb2c85dd2e6fcaf2fa1eb8ecddcbb9d91c36 Mon Sep 17 00:00:00 2001 From: Diject Date: Fri, 2 Jan 2026 19:52:04 +0300 Subject: [PATCH] Add configurable tilemap downscale factor --- apps/openmw/engine.cpp | 8 +++++++- apps/openmw/engine.hpp | 3 ++- apps/openmw/main.cpp | 1 + apps/openmw/mwworld/worldimp.cpp | 31 +++++++++++++++++-------------- apps/openmw/mwworld/worldimp.hpp | 3 ++- apps/openmw/options.cpp | 3 +++ 6 files changed, 32 insertions(+), 17 deletions(-) diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index b58993939f..b16876cca8 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -380,6 +380,7 @@ OMW::Engine::Engine(Files::ConfigurationManager& configurationManager) , mCfgMgr(configurationManager) , mGlMaxTextureImageUnits(0) , mOverwriteMaps(false) + , mTilemapDownscaleFactor(4) { #if SDL_VERSION_ATLEAST(2, 24, 0) SDL_SetHint(SDL_HINT_MAC_OPENGL_ASYNC_DISPATCH, "1"); @@ -839,7 +840,7 @@ void OMW::Engine::prepareEngine() // Create the world mWorld = std::make_unique( mResourceSystem.get(), mActivationDistanceOverride, mCellName, mCfgMgr.getUserDataPath(), - mWorldMapOutput, mLocalMapOutput, mOverwriteMaps); + mWorldMapOutput, mLocalMapOutput, mOverwriteMaps, mTilemapDownscaleFactor); mEnvironment.setWorld(*mWorld); mEnvironment.setWorldModel(mWorld->getWorldModel()); mEnvironment.setESMStore(mWorld->getStore()); @@ -1165,3 +1166,8 @@ void OMW::Engine::setOverwriteMaps(bool overwrite) { mOverwriteMaps = overwrite; } + +void OMW::Engine::setTilemapDownscaleFactor(int factor) +{ + mTilemapDownscaleFactor = factor; +} diff --git a/apps/openmw/engine.hpp b/apps/openmw/engine.hpp index 89ab520cba..648e3a7c59 100644 --- a/apps/openmw/engine.hpp +++ b/apps/openmw/engine.hpp @@ -186,6 +186,7 @@ namespace OMW std::string mWorldMapOutput; std::string mLocalMapOutput; bool mOverwriteMaps; + int mTilemapDownscaleFactor; Files::ConfigurationManager& mCfgMgr; int mGlMaxTextureImageUnits; @@ -274,7 +275,7 @@ namespace OMW void setOverwriteMaps(bool overwrite); - void setExtractMaps(bool extract); + void setTilemapDownscaleFactor(int factor); void setRecastMaxLogLevel(Debug::Level value) { mMaxRecastLogLevel = value; } }; diff --git a/apps/openmw/main.cpp b/apps/openmw/main.cpp index f50da3312c..102d142635 100644 --- a/apps/openmw/main.cpp +++ b/apps/openmw/main.cpp @@ -185,6 +185,7 @@ bool parseOptions(int argc, char** argv, OMW::Engine& engine, Files::Configurati engine.setWorldMapOutput(worldMapOutput); engine.setLocalMapOutput(localMapOutput); engine.setOverwriteMaps(variables["overwrite-maps"].as()); + engine.setTilemapDownscaleFactor(variables["tilemap-downscale-factor"].as()); return true; } diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 29fc464522..ee8f39f5dc 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -255,7 +255,7 @@ namespace MWWorld } World::World(Resource::ResourceSystem* resourceSystem, int activationDistanceOverride, const std::string& startCell, - const std::filesystem::path& userDataPath, const std::string& worldMapOutputPath, const std::string& localMapOutputPath, bool overwriteMaps) + const std::filesystem::path& userDataPath, const std::string& worldMapOutputPath, const std::string& localMapOutputPath, bool overwriteMaps, int tilemapDownscaleFactor) : mResourceSystem(resourceSystem) , mLocalScripts(mStore) , mWorldModel(mStore, mReaders) @@ -270,6 +270,7 @@ namespace MWWorld , mWorldMapOutputPath(worldMapOutputPath) , mLocalMapOutputPath(localMapOutputPath) , mOverwriteMaps(overwriteMaps) + , mTilemapDownscaleFactor(tilemapDownscaleFactor) , mSwimHeightScale(0.f) , mDistanceToFocusObject(-1.f) , mTeleportEnabled(true) @@ -4047,8 +4048,9 @@ namespace MWWorld Log(Debug::Info) << "Bounds: X=[" << minX << ", " << maxX << "], Y=[" << minY << ", " << maxY << "]"; // Step 2: Create the output image - const int width = (maxX - minX + 1) * 32; - const int height = (maxY - minY + 1) * 32; + const int targetSize = 256 / mTilemapDownscaleFactor; + const int width = (maxX - minX + 1) * targetSize; + const int height = (maxY - minY + 1) * targetSize; osg::ref_ptr tilemapImage = new osg::Image; tilemapImage->allocateImage(width, height, 1, GL_RGB, GL_UNSIGNED_BYTE); @@ -4079,17 +4081,18 @@ namespace MWWorld continue; } - // Downscale from 256x256 to 32x32 + // Downscale from 256x256 to target size based on downscale factor + const int targetSize = 256 / mTilemapDownscaleFactor; osg::ref_ptr scaledTile = new osg::Image; - scaledTile->allocateImage(32, 32, 1, tileImage->getPixelFormat(), tileImage->getDataType()); + scaledTile->allocateImage(targetSize, targetSize, 1, tileImage->getPixelFormat(), tileImage->getDataType()); // Simple nearest-neighbor downscaling - for (int y = 0; y < 32; ++y) + for (int y = 0; y < targetSize; ++y) { - for (int x = 0; x < 32; ++x) + for (int x = 0; x < targetSize; ++x) { - int srcX = (x * tileImage->s()) / 32; - int srcY = (y * tileImage->t()) / 32; + int srcX = (x * tileImage->s()) / targetSize; + int srcY = (y * tileImage->t()) / targetSize; unsigned char* srcPixel = tileImage->data(srcX, srcY); unsigned char* dstPixel = scaledTile->data(x, y); @@ -4103,12 +4106,12 @@ namespace MWWorld } // Place scaled tile in output image - int destX = (gridX - minX) * 32; - int destY = (gridY - minY) * 32; + int destX = (gridX - minX) * targetSize; + int destY = (gridY - minY) * targetSize; - for (int y = 0; y < 32; ++y) + for (int y = 0; y < targetSize; ++y) { - for (int x = 0; x < 32; ++x) + for (int x = 0; x < targetSize; ++x) { unsigned char* srcPixel = scaledTile->data(x, y); unsigned char* dstPixel = tilemapImage->data(destX + x, destY + y); @@ -4144,7 +4147,7 @@ namespace MWWorld return; } - const int pixelsPerCell = 256 / 8; // Тайлы 32x32 при downscale factor = 8 + const int pixelsPerCell = 256 / mTilemapDownscaleFactor; infoFile << "width: " << width << "\n"; infoFile << "height: " << height << "\n"; diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 7b6dd2bd54..1eb0583869 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -124,6 +124,7 @@ namespace MWWorld std::string mWorldMapOutputPath; std::string mLocalMapOutputPath; bool mOverwriteMaps; + int mTilemapDownscaleFactor; float mSwimHeightScale; @@ -201,7 +202,7 @@ namespace MWWorld void removeContainerScripts(const Ptr& reference) override; World(Resource::ResourceSystem* resourceSystem, int activationDistanceOverride, const std::string& startCell, - const std::filesystem::path& userDataPath, const std::string& worldMapOutputPath, const std::string& localMapOutputPath, bool overwriteMaps); + const std::filesystem::path& userDataPath, const std::string& worldMapOutputPath, const std::string& localMapOutputPath, bool overwriteMaps, int tilemapDownscaleFactor); void loadData(const Files::Collections& fileCollections, const std::vector& contentFiles, const std::vector& groundcoverFiles, ToUTF8::Utf8Encoder* encoder, diff --git a/apps/openmw/options.cpp b/apps/openmw/options.cpp index 356a98bb79..536f8267bc 100644 --- a/apps/openmw/options.cpp +++ b/apps/openmw/options.cpp @@ -104,6 +104,9 @@ namespace OpenMW addOption("overwrite-maps", bpo::value()->implicit_value(true)->default_value(false), "overwrite existing map files during extraction"); + addOption("tilemap-downscale-factor", bpo::value()->default_value(4), + "downscale factor for tilemap generation (must be power of 2, default: 4)"); + return desc; } }