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 f5ded321..00000000 Binary files a/cache/wmo_floor_cache.bin and /dev/null differ diff --git a/include/rendering/wmo_renderer.hpp b/include/rendering/wmo_renderer.hpp index 3f8e9997..45fa79fd 100644 --- a/include/rendering/wmo_renderer.hpp +++ b/include/rendering/wmo_renderer.hpp @@ -222,9 +222,11 @@ public: double getQueryTimeMs() const { return queryTimeMs; } uint32_t getQueryCallCount() const { return queryCallCount; } - // Floor cache persistence - bool saveFloorCache(const std::string& filepath) const; - bool loadFloorCache(const std::string& filepath); + // Floor cache persistence (zone-specific files) + void setMapName(const std::string& name) { mapName_ = name; } + const std::string& getMapName() const { return mapName_; } + bool saveFloorCache() const; // Saves to cache/wmo_floor_.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; }