fix(wmo): disable portal traversal for outdoor camera groups

This commit is contained in:
Kelsi 2026-03-14 05:57:27 -07:00
parent a2f9ccc9b9
commit d7a0a9f675

View file

@ -2054,6 +2054,9 @@ void WMORenderer::getVisibleGroupsViaPortals(const ModelData& model,
const Frustum& frustum,
const glm::mat4& modelMatrix,
std::unordered_set<uint32_t>& outVisibleGroups) const {
constexpr uint32_t WMO_GROUP_FLAG_OUTDOOR = 0x8;
constexpr uint32_t WMO_GROUP_FLAG_INDOOR = 0x2000;
// Find camera's containing group
int cameraGroup = findContainingGroup(model, cameraLocalPos);
@ -2067,6 +2070,21 @@ void WMORenderer::getVisibleGroupsViaPortals(const ModelData& model,
return;
}
// Outdoor city WMOs (e.g. Stormwind) often have portal graphs that are valid for
// indoor visibility but too aggressive outdoors, causing direction-dependent popout.
// Only trust portal traversal when the camera is in an interior-only group.
if (cameraGroup < static_cast<int>(model.groups.size())) {
const uint32_t gFlags = model.groups[cameraGroup].groupFlags;
const bool isIndoor = (gFlags & WMO_GROUP_FLAG_INDOOR) != 0;
const bool isOutdoor = (gFlags & WMO_GROUP_FLAG_OUTDOOR) != 0;
if (!isIndoor || isOutdoor) {
for (size_t gi = 0; gi < model.groups.size(); gi++) {
outVisibleGroups.insert(static_cast<uint32_t>(gi));
}
return;
}
}
// If the camera group has no portal refs, it's a dead-end group (utility/transition group).
// Fall back to showing all groups to avoid the rest of the WMO going invisible.
if (cameraGroup < static_cast<int>(model.groupPortalRefs.size())) {