diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp index 05305cc2..9f85c3d5 100644 --- a/src/rendering/renderer.cpp +++ b/src/rendering/renderer.cpp @@ -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(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(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, diff --git a/src/rendering/wmo_renderer.cpp b/src/rendering/wmo_renderer.cpp index bc9aa362..4207b24b 100644 --- a/src/rendering/wmo_renderer.cpp +++ b/src/rendering/wmo_renderer.cpp @@ -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(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(gi)); + } + return; + } + } + // BFS through portals from camera's group std::vector visited(model.groups.size(), false); std::vector queue;