diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 82865e6532..2f54a2ec66 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -97,7 +97,8 @@ void BackendRenderer::AcceptMessage(ref_ptr message) if (!tiles.empty()) { ScreenBase const screen = m_requestedTiles->GetScreen(); - m_readManager->UpdateCoverage(screen, tiles, m_texMng); + bool const is3dBuildings = m_requestedTiles->Is3dBuildings(); + m_readManager->UpdateCoverage(screen, is3dBuildings, tiles, m_texMng); gui::CountryStatusHelper & helper = gui::DrapeGui::Instance().GetCountryStatusHelper(); if ((*tiles.begin()).m_zoomLevel > scales::GetUpperWorldScale()) diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index d17bcfb23c..6b753d01ba 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -429,14 +429,15 @@ gui::TWidgetsSizeInfo const & DrapeEngine::GetWidgetSizes() return m_widgetSizes; } -void DrapeEngine::Allow3dMode(bool allow3d, bool allow3dBuildings, double rotationAngle, double angleFOV) +void DrapeEngine::Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings, double rotationAngle, double angleFOV) { m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(allow3d && allow3dBuildings), + make_unique_dp(allow3dBuildings), MessagePriority::Normal); m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(allow3d, rotationAngle, angleFOV), + make_unique_dp(allowPerspectiveInNavigation, allow3dBuildings, + rotationAngle, angleFOV), MessagePriority::Normal); } diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 4d138a7885..8184a79177 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -114,7 +114,7 @@ public: void SetWidgetLayout(gui::TWidgetsLayoutInfo && info); gui::TWidgetsSizeInfo const & GetWidgetSizes(); - void Allow3dMode(bool allow3d, bool allow3dBuildings, double rotationAngle, double angleFOV); + void Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings, double rotationAngle, double angleFOV); void EnablePerspective(double rotationAngle, double angleFOV); private: diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index c290833896..64bad412d3 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -47,7 +47,9 @@ FrontendRenderer::FrontendRenderer(Params const & params) , m_framebuffer(new Framebuffer()) , m_transparentLayer(new TransparentLayer()) , m_overlayTree(new dp::OverlayTree()) - , m_enable3dInNavigation(false) + , m_enablePerspectiveInNavigation(false) + , m_enable3dBuildings(false) + , m_isIsometry(false) , m_viewport(params.m_viewport) , m_userEventStream(params.m_isCountryLoadedFn) , m_modelViewChangedFn(params.m_modelViewChangedFn) @@ -197,7 +199,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) MessagePriority::High); blocker.Wait(); - m_requestedTiles->Set(screen, move(tiles)); + m_requestedTiles->Set(screen, m_isIsometry || screen.isPerspective(), move(tiles)); m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, make_unique_dp(), MessagePriority::UberHighSingleton); @@ -403,7 +405,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) { m_myPositionController->DeactivateRouting(); m_overlayTree->SetFollowingMode(false); - if (m_enable3dInNavigation) + if (m_enablePerspectiveInNavigation) DisablePerspective(); } break; @@ -412,10 +414,10 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) case Message::FollowRoute: { ref_ptr const msg = message; - m_myPositionController->NextMode(!m_enable3dInNavigation ? msg->GetPreferredZoomLevel() + m_myPositionController->NextMode(!m_enablePerspectiveInNavigation ? msg->GetPreferredZoomLevel() : msg->GetPreferredZoomLevelIn3d()); m_overlayTree->SetFollowingMode(true); - if (m_enable3dInNavigation) + if (m_enablePerspectiveInNavigation) { bool immediatelyStart = !m_myPositionController->IsRotationActive(); AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(), @@ -428,7 +430,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) { m_myPositionController->DeactivateRouting(); m_overlayTree->SetFollowingMode(false); - if (m_enable3dInNavigation) + if (m_enablePerspectiveInNavigation) DisablePerspective(); break; } @@ -495,7 +497,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) } // Request new tiles. - m_requestedTiles->Set(screen, move(tiles)); + m_requestedTiles->Set(screen, m_isIsometry || screen.isPerspective(), move(tiles)); m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, make_unique_dp(), MessagePriority::UberHighSingleton); @@ -518,27 +520,28 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) ref_ptr const msg = message; bool const isPerspective = m_userEventStream.GetCurrentScreen().isPerspective(); #ifdef OMIM_OS_DESKTOP - if (m_enable3dInNavigation == msg->Allow() && - m_enable3dInNavigation != isPerspective) + if (m_enablePerspectiveInNavigation == msg->AllowPerspective() && + m_enablePerspectiveInNavigation != isPerspective) { - if (m_enable3dInNavigation) + if (m_enablePerspectiveInNavigation) AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(), false /* animated */, true /* immediately start */)); else AddUserEvent(DisablePerspectiveEvent()); } #endif - m_enable3dInNavigation = msg->Allow(); + m_enablePerspectiveInNavigation = msg->AllowPerspective(); + m_enable3dBuildings = msg->Allow3dBuildings(); if (m_myPositionController->IsInRouting()) { - if (m_enable3dInNavigation && !isPerspective && !m_perspectiveDiscarded) + if (m_enablePerspectiveInNavigation && !isPerspective && !m_perspectiveDiscarded) { AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(), true /* animated */, true /* immediately start */)); } - else if (!m_enable3dInNavigation && (isPerspective || m_perspectiveDiscarded)) + else if (!m_enablePerspectiveInNavigation && (isPerspective || m_perspectiveDiscarded)) { DisablePerspective(); } @@ -574,8 +577,7 @@ void FrontendRenderer::OnResize(ScreenBase const & screen) RefreshProjection(screen); RefreshPivotTransform(screen); - if (screen.isPerspective()) - m_framebuffer->SetSize(viewportRect.SizeX(), viewportRect.SizeY()); + m_framebuffer->SetSize(viewportRect.SizeX(), viewportRect.SizeY()); } void FrontendRenderer::AddToRenderGroup(vector> & groups, @@ -780,7 +782,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) dp::GLState const & state = group->GetState(); - if (isPerspective && state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM) + if ((isPerspective || m_isIsometry) && state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM) { if (!has3dAreas) { @@ -822,7 +824,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView) m_myPositionController->Render(MyPositionController::RenderAccuracy, modelView, make_ref(m_gpuProgramManager), m_generalUniforms); - if (isPerspective && has3dAreas) + if (has3dAreas) { m_framebuffer->Enable(); GLFunctions::glClear(); @@ -938,8 +940,18 @@ void FrontendRenderer::RefreshPivotTransform(ScreenBase const & screen) math::Matrix transform(screen.Pto3dMatrix()); m_generalUniforms.SetMatrix4x4Value("pivotTransform", transform.m_data); } + else if (m_isIsometry) + { + math::Matrix transform(math::Identity()); + transform(2, 1) = -1.0f/tan(M_PI * 80.0f / 180.0f); + transform(2, 2) = 1.0f / screen.GetHeight(); + m_generalUniforms.SetMatrix4x4Value("pivotTransform", transform.m_data); + } else - m_generalUniforms.SetMatrix4x4Value("pivotTransform", math::Identity().m_data); + { + math::Matrix transform(math::Identity()); + m_generalUniforms.SetMatrix4x4Value("pivotTransform", transform.m_data); + } } void FrontendRenderer::RefreshBgColor() @@ -968,11 +980,13 @@ void FrontendRenderer::DisablePerspective() void FrontendRenderer::CheckMinAllowableIn3dScale() { - if (!m_enable3dInNavigation || - m_userEventStream.IsInPerspectiveAnimation()) + bool const isScaleAllowableIn3d = UserEventStream::IsScaleAllowableIn3d(m_currentZoomLevel); + m_isIsometry = m_enable3dBuildings && isScaleAllowableIn3d; + + if (!m_enablePerspectiveInNavigation || m_userEventStream.IsInPerspectiveAnimation()) return; - bool const switchTo2d = !UserEventStream::IsScaleAllowableIn3d(m_currentZoomLevel); + bool const switchTo2d = !isScaleAllowableIn3d; if ((!switchTo2d && !m_perspectiveDiscarded) || (switchTo2d && !m_userEventStream.GetCurrentScreen().isPerspective())) return; @@ -1328,7 +1342,7 @@ void FrontendRenderer::UpdateScene(ScreenBase const & modelView) }; RemoveRenderGroups(removePredicate); - m_requestedTiles->Set(modelView, move(tiles)); + m_requestedTiles->Set(modelView, m_isIsometry || modelView.isPerspective(), move(tiles)); m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, make_unique_dp(), MessagePriority::UberHighSingleton); diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index bdfa3e83b0..352c2744dd 100755 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -234,7 +234,9 @@ private: dp::UniformValuesStorage m_generalUniforms; - bool m_enable3dInNavigation; + bool m_enablePerspectiveInNavigation; + bool m_enable3dBuildings; + bool m_isIsometry; Viewport m_viewport; UserEventStream m_userEventStream; diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index 67d465290d..3f1a1dd814 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -656,19 +656,22 @@ public: class Allow3dModeMessage : public Message { public: - Allow3dModeMessage(bool allow, double rotationAngle, double angleFOV) - : m_allow(allow) + Allow3dModeMessage(bool allowPerspective, bool allow3dBuildings, double rotationAngle, double angleFOV) + : m_allowPerspective(allowPerspective) + , m_allow3dBuildings(allow3dBuildings) , m_rotationAngle(rotationAngle) , m_angleFOV(angleFOV) {} Type GetType() const override { return Message::Allow3dMode; } - bool Allow() const { return m_allow; } + bool AllowPerspective() const { return m_allowPerspective; } + bool Allow3dBuildings() const { return m_allow3dBuildings; } double GetRotationAngle() const { return m_rotationAngle; } double GetAngleFOV() const { return m_angleFOV; } private: - bool const m_allow; + bool const m_allowPerspective; + bool const m_allow3dBuildings; double const m_rotationAngle; double const m_angleFOV; }; diff --git a/drape_frontend/read_manager.cpp b/drape_frontend/read_manager.cpp index e1a76f3cfe..84c301fd98 100755 --- a/drape_frontend/read_manager.cpp +++ b/drape_frontend/read_manager.cpp @@ -36,8 +36,8 @@ ReadManager::ReadManager(ref_ptr commutator, MapDataProvider , m_model(model) , m_pool(make_unique_dp(ReadCount(), bind(&ReadManager::OnTaskFinished, this, _1))) , m_forceUpdate(true) - , m_is3d(false) - , m_is3dBuildings(false) + , m_need3dBuildings(false) + , m_allow3dBuildings(false) , m_modeChanged(false) , myPool(64, ReadMWMTaskFactory(m_memIndex, m_model)) , m_counter(0) @@ -73,14 +73,15 @@ void ReadManager::OnTaskFinished(threads::IRoutine * task) myPool.Return(t); } -void ReadManager::UpdateCoverage(ScreenBase const & screen, TTilesCollection const & tiles, ref_ptr texMng) +void ReadManager::UpdateCoverage(ScreenBase const & screen, bool is3dBuildings, + TTilesCollection const & tiles, ref_ptr texMng) { if (screen == m_currentViewport && !m_forceUpdate) return; m_forceUpdate = false; - m_is3d = screen.isPerspective(); - m_modeChanged |= m_is3dBuildings && (m_is3d != m_currentViewport.isPerspective()); + m_modeChanged |= m_need3dBuildings != is3dBuildings; + m_need3dBuildings = is3dBuildings; if (m_modeChanged || MustDropAllTiles(screen)) { @@ -188,7 +189,7 @@ void ReadManager::PushTaskBackForTileKey(TileKey const & tileKey, ref_ptr tileInfo(new TileInfo(make_unique_dp(TileKey(tileKey, m_generationCounter), m_commutator, texMng))); - tileInfo->Set3dBuildings(m_is3d && m_is3dBuildings); + tileInfo->Set3dBuildings(m_need3dBuildings && m_allow3dBuildings); m_tileInfos.insert(tileInfo); ReadMWMTask * task = myPool.Get(); task->Init(tileInfo); @@ -197,7 +198,7 @@ void ReadManager::PushTaskBackForTileKey(TileKey const & tileKey, ref_ptr const & tileToReread) { - tileToReread->Set3dBuildings(m_is3d && m_is3dBuildings); + tileToReread->Set3dBuildings(m_need3dBuildings && m_allow3dBuildings); ReadMWMTask * task = myPool.Get(); task->Init(tileToReread); m_pool->PushFront(task); @@ -222,11 +223,11 @@ void ReadManager::IncreaseCounter(int value) void ReadManager::Allow3dBuildings(bool allow3dBuildings) { - if (m_is3dBuildings != allow3dBuildings) + if (m_allow3dBuildings != allow3dBuildings) { m_modeChanged = true; m_forceUpdate = true; - m_is3dBuildings = allow3dBuildings; + m_allow3dBuildings = allow3dBuildings; } } diff --git a/drape_frontend/read_manager.hpp b/drape_frontend/read_manager.hpp index cd6778b0fe..34fba548cf 100755 --- a/drape_frontend/read_manager.hpp +++ b/drape_frontend/read_manager.hpp @@ -30,7 +30,7 @@ class ReadManager public: ReadManager(ref_ptr commutator, MapDataProvider & model); - void UpdateCoverage(ScreenBase const & screen, TTilesCollection const & tiles, + void UpdateCoverage(ScreenBase const & screen, bool is3dBuildings, TTilesCollection const & tiles, ref_ptr texMng); void Invalidate(TTilesCollection const & keyStorage); void Stop(); @@ -57,8 +57,8 @@ private: ScreenBase m_currentViewport; bool m_forceUpdate; - bool m_is3d; - bool m_is3dBuildings; + bool m_need3dBuildings; + bool m_allow3dBuildings; bool m_modeChanged; struct LessByTileInfo diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index 594e94189f..0ee5139a80 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -181,7 +181,8 @@ void RenderGroup::Disappear() //else { // Create separate disappearing animation for area objects to eliminate flickering. - if (m_state.GetProgramIndex() == gpu::AREA_PROGRAM) + if (m_state.GetProgramIndex() == gpu::AREA_PROGRAM || + m_state.GetProgramIndex() == gpu::AREA_3D_PROGRAM) m_disappearAnimation = make_unique(0.01 /* duration */, 0.25 /* delay */, 1.0 /* startOpacity */, 1.0 /* endOpacity */); } diff --git a/drape_frontend/requested_tiles.cpp b/drape_frontend/requested_tiles.cpp index 76d0cf4bfe..9218e45f2b 100755 --- a/drape_frontend/requested_tiles.cpp +++ b/drape_frontend/requested_tiles.cpp @@ -3,11 +3,12 @@ namespace df { -void RequestedTiles::Set(ScreenBase const & screen, TTilesCollection && tiles) +void RequestedTiles::Set(ScreenBase const & screen, bool is3dBuildings, TTilesCollection && tiles) { lock_guard lock(m_mutex); m_tiles = move(tiles); m_screen = screen; + m_is3dBuildings = is3dBuildings; } TTilesCollection RequestedTiles::GetTiles() diff --git a/drape_frontend/requested_tiles.hpp b/drape_frontend/requested_tiles.hpp index c9bbd22d69..b3e44ee882 100755 --- a/drape_frontend/requested_tiles.hpp +++ b/drape_frontend/requested_tiles.hpp @@ -13,14 +13,16 @@ class RequestedTiles { public: RequestedTiles() = default; - void Set(ScreenBase const & screen, TTilesCollection && tiles); + void Set(ScreenBase const & screen, bool is3dBuildings, TTilesCollection && tiles); TTilesCollection GetTiles(); ScreenBase GetScreen(); + bool Is3dBuildings() const { return m_is3dBuildings; } bool CheckTileKey(TileKey const & tileKey) const; private: TTilesCollection m_tiles; ScreenBase m_screen; + bool m_is3dBuildings = false; mutable mutex m_mutex; };