From 76c4268ed8346e42dfbe321aaa4c858b378fffb1 Mon Sep 17 00:00:00 2001 From: Kelsi Date: Thu, 5 Feb 2026 17:35:17 -0800 Subject: [PATCH] Use zone-specific floor cache files Save/load floor cache per map (e.g., cache/wmo_floor_Azeroth.bin) instead of a single global file. Saves current zone's cache before teleporting, loads target zone's cache after terrain streaming completes. --- .gitignore | 3 ++ cache/wmo_floor_cache.bin | Bin 1912 -> 0 bytes include/rendering/wmo_renderer.hpp | 11 ++++++-- src/core/application.cpp | 43 ++++++++++++++++++++--------- src/rendering/wmo_renderer.cpp | 24 ++++++++++++---- 5 files changed, 60 insertions(+), 21 deletions(-) delete mode 100644 cache/wmo_floor_cache.bin diff --git a/.gitignore b/.gitignore index fc617522..8374c870 100644 --- a/.gitignore +++ b/.gitignore @@ -61,3 +61,6 @@ Data/ # Texture assets (not distributed - see README) assets/textures/ + +# Runtime cache (floor heights, etc.) +cache/ diff --git a/cache/wmo_floor_cache.bin b/cache/wmo_floor_cache.bin deleted file mode 100644 index f5ded321a5608078b4e233c77593325490f2457b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1912 zcmYk7TWC~g6opf)Rq*&DMZ*K<-1Xecd?0@aG zFIm;HF8fMdUEO~9<>xK=++ zsXeu?sI{ZHqa5pOprLapadU-(w#L^Z?IX1`{N>&I633IC=|$Dg46MFwGeC{)S8O)$ zu&^yrKjG)A<|iJO2h2}q=7$Z5dWfI(Uq-4KJzYcQC-a$cq3S`~tV8y$7u@|Y(t4@o z<7YOv_|Ub*t0(x7eH^HMe8_J0njcR3O|Lyg|AD__ttEi-YEku&zu~m$K|}gdsCm$K zcs$ge>iqm`?^Y$AlHRdL@Yl;8G26V=_9W20vqyKX2igm~O;j_$J!TaZ+WrH zASENQXqyK)L%_@3wqgF3^b`4s+cvAQ37;IW+DklLP-pW9W6ZO6&kf8M*L z60hA){DG5t;&ra@r*@aX#mS-i$-Aw461}}><_>TxD)5KwUHt4nW}Xwz{b8Q-Zu3Ul zP5ROzGr&D0f71o?0Z)eI&J)LnN#9$I=)5Jjk=x5{yz{x$LcOiy7Kfku%I8#QAkB7~_8UJMt@$O;cP-9hU$Iq8J#2e(c^ZyHPcMW>& zJ9=tw(YuMC%tLZE3WwU6r9Qcb+.bin + bool loadFloorCache(); // Loads from cache/wmo_floor_.bin size_t getFloorCacheSize() const { return precomputedFloorGrid.size(); } // Pre-compute floor cache for all loaded WMO instances @@ -428,6 +430,9 @@ private: // Asset manager for loading textures pipeline::AssetManager* assetManager = nullptr; + // Current map name for zone-specific floor cache + std::string mapName_; + // Texture cache (path -> texture ID) std::unordered_map textureCache; diff --git a/src/core/application.cpp b/src/core/application.cpp index d24bc81c..cf1bed33 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -146,11 +146,6 @@ bool Application::initialize() { return false; } - // Load cached floor heights for faster collision - if (renderer->getWMORenderer()) { - renderer->getWMORenderer()->loadFloorCache("cache/wmo_floor_cache.bin"); - } - // Create UI manager uiManager = std::make_unique(); if (!uiManager->initialize(window.get())) { @@ -320,7 +315,7 @@ void Application::shutdown() { size_t cacheSize = renderer->getWMORenderer()->getFloorCacheSize(); if (cacheSize > 0) { LOG_INFO("Saving WMO floor cache (", cacheSize, " entries)..."); - renderer->getWMORenderer()->saveFloorCache("cache/wmo_floor_cache.bin"); + renderer->getWMORenderer()->saveFloorCache(); } } @@ -1207,6 +1202,11 @@ void Application::startSinglePlayer() { showStatus("Loading terrain..."); + // Set map name for zone-specific floor cache + if (renderer->getWMORenderer()) { + renderer->getWMORenderer()->setMapName(mapName); + } + // Try to load test terrain if WOW_DATA_PATH is set bool terrainOk = false; if (renderer && assetManager && assetManager->isInitialized()) { @@ -1270,10 +1270,13 @@ void Application::startSinglePlayer() { LOG_INFO("Terrain streaming complete: ", terrainMgr->getLoadedTileCount(), " tiles loaded"); - // Pre-compute floor cache if it wasn't loaded from file - if (renderer->getWMORenderer() && renderer->getWMORenderer()->getFloorCacheSize() == 0) { - showStatus("Pre-computing collision cache..."); - renderer->getWMORenderer()->precomputeFloorCache(); + // Load zone-specific floor cache, or precompute if none exists + if (renderer->getWMORenderer()) { + renderer->getWMORenderer()->loadFloorCache(); + if (renderer->getWMORenderer()->getFloorCacheSize() == 0) { + showStatus("Pre-computing collision cache..."); + renderer->getWMORenderer()->precomputeFloorCache(); + } } // Re-snap camera to ground now that all surrounding tiles are loaded @@ -1348,6 +1351,14 @@ void Application::teleportTo(int presetIndex) { renderer->getCameraController()->setDefaultSpawn(spawnRender, preset.yawDeg, preset.pitchDeg); } + // Save current map's floor cache before unloading + if (renderer && renderer->getWMORenderer()) { + auto* wmo = renderer->getWMORenderer(); + if (wmo->getFloorCacheSize() > 0) { + wmo->saveFloorCache(); + } + } + // Unload all current terrain if (renderer && renderer->getTerrainManager()) { renderer->getTerrainManager()->unloadAll(); @@ -1360,10 +1371,13 @@ void Application::teleportTo(int presetIndex) { std::to_string(tileX) + "_" + std::to_string(tileY) + ".adt"; LOG_INFO("Teleport ADT tile [", tileX, ",", tileY, "]"); - // Set map name on terrain manager + // Set map name on terrain manager and WMO renderer if (renderer && renderer->getTerrainManager()) { renderer->getTerrainManager()->setMapName(mapName); } + if (renderer && renderer->getWMORenderer()) { + renderer->getWMORenderer()->setMapName(mapName); + } // Load the initial tile bool terrainOk = false; @@ -1403,9 +1417,12 @@ void Application::teleportTo(int presetIndex) { LOG_INFO("Teleport terrain streaming complete: ", terrainMgr->getLoadedTileCount(), " tiles loaded"); - // Pre-compute floor cache for the new area + // Load zone-specific floor cache, or precompute if none exists if (renderer->getWMORenderer()) { - renderer->getWMORenderer()->precomputeFloorCache(); + renderer->getWMORenderer()->loadFloorCache(); + if (renderer->getWMORenderer()->getFloorCacheSize() == 0) { + renderer->getWMORenderer()->precomputeFloorCache(); + } } } diff --git a/src/rendering/wmo_renderer.cpp b/src/rendering/wmo_renderer.cpp index 0057f531..376f0ca1 100644 --- a/src/rendering/wmo_renderer.cpp +++ b/src/rendering/wmo_renderer.cpp @@ -514,7 +514,14 @@ void WMORenderer::resetQueryStats() { // Note: precomputedFloorGrid is persistent and not cleared per-frame } -bool WMORenderer::saveFloorCache(const std::string& filepath) const { +bool WMORenderer::saveFloorCache() const { + if (mapName_.empty()) { + core::Logger::getInstance().warning("Cannot save floor cache: no map name set"); + return false; + } + + std::string filepath = "cache/wmo_floor_" + mapName_ + ".bin"; + // Create directory if needed std::filesystem::path path(filepath); std::filesystem::path absPath = std::filesystem::absolute(path); @@ -549,14 +556,21 @@ bool WMORenderer::saveFloorCache(const std::string& filepath) const { file.write(reinterpret_cast(&height), sizeof(height)); } - core::Logger::getInstance().info("Saved WMO floor cache: ", count, " entries to ", filepath); + core::Logger::getInstance().info("Saved WMO floor cache (", mapName_, "): ", count, " entries"); return true; } -bool WMORenderer::loadFloorCache(const std::string& filepath) { +bool WMORenderer::loadFloorCache() { + if (mapName_.empty()) { + core::Logger::getInstance().warning("Cannot load floor cache: no map name set"); + return false; + } + + std::string filepath = "cache/wmo_floor_" + mapName_ + ".bin"; + std::ifstream file(filepath, std::ios::binary); if (!file) { - core::Logger::getInstance().info("No existing floor cache file: ", filepath); + core::Logger::getInstance().info("No existing floor cache for map: ", mapName_); return false; } @@ -585,7 +599,7 @@ bool WMORenderer::loadFloorCache(const std::string& filepath) { precomputedFloorGrid[key] = height; } - core::Logger::getInstance().info("Loaded WMO floor cache: ", precomputedFloorGrid.size(), " entries from ", filepath); + core::Logger::getInstance().info("Loaded WMO floor cache (", mapName_, "): ", precomputedFloorGrid.size(), " entries"); return true; }