fix: WMO culling dead-end group fallback and minimap arrow direction

wmo_renderer: when portal BFS starts from a group with no portal refs
(utility/transition group), the rest of the WMO becomes invisible because
BFS only adds the starting group. Fix: if cameraGroup has portalCount==0,
fall back to marking all groups visible (same as camera-outside behavior).

renderer: minimap player-orientation arrow was pointing the wrong direction.
The shader convention is arrowRotation=0→North, positive→clockwise (West),
negative→East. The correct mapping from canonical yaw is arrowRotation =
-canonical_yaw. Fixed both render paths (cameraController and gameHandler)
in both the FXAA and non-FXAA minimap render calls.

World-map W-key: already corrected in prior commit (13c096f); users with
stale ~/.wowee/settings.cfg should rebind via Settings > Controls.
This commit is contained in:
Kelsi 2026-03-13 02:25:06 -07:00
parent d4bf8c871e
commit 862d743f87
2 changed files with 24 additions and 12 deletions

View file

@ -5256,14 +5256,14 @@ void Renderer::renderWorld(game::World* world, game::GameHandler* gameHandler) {
if (cameraController) {
float facingRad = glm::radians(characterYaw);
glm::vec3 facingFwd(std::cos(facingRad), std::sin(facingRad), 0.0f);
minimapPlayerOrientation = std::atan2(-facingFwd.x, facingFwd.y);
// atan2(-x,y) = canonical yaw (0=North); negate for shader convention.
minimapPlayerOrientation = -std::atan2(-facingFwd.x, facingFwd.y);
hasMinimapPlayerOrientation = true;
} else if (gameHandler) {
// Server orientation is in WoW space: π/2 = North, 0 = East.
// Minimap arrow expects render space: 0 = North, π/2 = East.
// Convert: minimap_angle = server_orientation - π/2
minimapPlayerOrientation = gameHandler->getMovementInfo().orientation
- static_cast<float>(M_PI_2);
// movementInfo.orientation is canonical yaw: 0=North, π/2=East.
// Minimap shader: arrowRotation=0 points up (North), positive rotates CW
// (π/2=West, -π/2=East). Correct mapping: arrowRotation = -canonical_yaw.
minimapPlayerOrientation = -gameHandler->getMovementInfo().orientation;
hasMinimapPlayerOrientation = true;
}
minimap->render(cmd, *camera, minimapCenter,
@ -5393,14 +5393,14 @@ void Renderer::renderWorld(game::World* world, game::GameHandler* gameHandler) {
if (cameraController) {
float facingRad = glm::radians(characterYaw);
glm::vec3 facingFwd(std::cos(facingRad), std::sin(facingRad), 0.0f);
minimapPlayerOrientation = std::atan2(-facingFwd.x, facingFwd.y);
// atan2(-x,y) = canonical yaw (0=North); negate for shader convention.
minimapPlayerOrientation = -std::atan2(-facingFwd.x, facingFwd.y);
hasMinimapPlayerOrientation = true;
} else if (gameHandler) {
// Server orientation is in WoW space: π/2 = North, 0 = East.
// Minimap arrow expects render space: 0 = North, π/2 = East.
// Convert: minimap_angle = server_orientation - π/2
minimapPlayerOrientation = gameHandler->getMovementInfo().orientation
- static_cast<float>(M_PI_2);
// movementInfo.orientation is canonical yaw: 0=North, π/2=East.
// Minimap shader: arrowRotation=0 points up (North), positive rotates CW
// (π/2=West, -π/2=East). Correct mapping: arrowRotation = -canonical_yaw.
minimapPlayerOrientation = -gameHandler->getMovementInfo().orientation;
hasMinimapPlayerOrientation = true;
}
minimap->render(currentCmd, *camera, minimapCenter,

View file

@ -2063,6 +2063,18 @@ void WMORenderer::getVisibleGroupsViaPortals(const ModelData& model,
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())) {
auto [portalStart, portalCount] = model.groupPortalRefs[cameraGroup];
if (portalCount == 0) {
for (size_t gi = 0; gi < model.groups.size(); gi++) {
outVisibleGroups.insert(static_cast<uint32_t>(gi));
}
return;
}
}
// BFS through portals from camera's group
std::vector<bool> visited(model.groups.size(), false);
std::vector<uint32_t> queue;