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.
This commit is contained in:
Kelsi 2026-02-05 17:35:17 -08:00
parent 1530900bc7
commit 76c4268ed8
5 changed files with 60 additions and 21 deletions

3
.gitignore vendored
View file

@ -61,3 +61,6 @@ Data/
# Texture assets (not distributed - see README)
assets/textures/
# Runtime cache (floor heights, etc.)
cache/

Binary file not shown.

View file

@ -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_<mapName>.bin
bool loadFloorCache(); // Loads from cache/wmo_floor_<mapName>.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<std::string, GLuint> textureCache;

View file

@ -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<ui::UIManager>();
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();
}
}
}

View file

@ -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<const char*>(&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;
}