Fix terrain streaming crash: pendingTiles data race and missing null checks

Guard pendingTiles.erase() with queueMutex in processReadyTiles and
unloadTile to prevent data race with worker threads. Add defensive null
checks in M2/WMO render and animation paths. Move cleanupUnusedModels
out of per-tile unload loop to run once after all tiles are removed.
This commit is contained in:
Kelsi 2026-02-07 18:57:34 -08:00
parent c156f3d390
commit 0d94bca896
3 changed files with 44 additions and 19 deletions

View file

@ -852,8 +852,11 @@ void WMORenderer::render(const Camera& camera, const glm::mat4& view, const glm:
bool doFrustumCull = frustumCulling;
auto cullInstance = [&](size_t instIdx) -> InstanceDrawList {
if (instIdx >= instances.size()) return InstanceDrawList{};
const auto& instance = instances[instIdx];
const ModelData& model = loadedModels.find(instance.modelId)->second;
auto mdlIt = loadedModels.find(instance.modelId);
if (mdlIt == loadedModels.end()) return InstanceDrawList{};
const ModelData& model = mdlIt->second;
InstanceDrawList result;
result.instanceIndex = instIdx;
@ -942,8 +945,11 @@ void WMORenderer::render(const Camera& camera, const glm::mat4& view, const glm:
// ── Phase 2: Sequential GL draw ────────────────────────────────
for (const auto& dl : drawLists) {
if (dl.instanceIndex >= instances.size()) continue;
const auto& instance = instances[dl.instanceIndex];
const ModelData& model = loadedModels.find(instance.modelId)->second;
auto modelIt = loadedModels.find(instance.modelId);
if (modelIt == loadedModels.end()) continue;
const ModelData& model = modelIt->second;
// Occlusion query pre-pass (GL calls — must be main thread)
if (occlusionCulling && occlusionShader && bboxVao != 0) {