diff --git a/drape/constants.hpp b/drape/constants.hpp index 1d1e463c62..77623f2e8b 100644 --- a/drape/constants.hpp +++ b/drape/constants.hpp @@ -6,8 +6,7 @@ namespace dp { namespace depth { -float constexpr POSITION_ACCURACY = minDepth + 1.0f; -float constexpr MY_POSITION_MARK = maxDepth - 1.0f; +float constexpr kMyPositionMarkDepth = maxDepth - 1.0f; } // namespace depth namespace displacement @@ -15,4 +14,6 @@ namespace displacement int constexpr kDefaultMode = 0x1; int constexpr kHotelMode = 0x2; } // namespace displacement + +uint32_t constexpr kScreenPixelRectExtension = 75; // in pixels. } // namespace dp diff --git a/drape/overlay_handle.hpp b/drape/overlay_handle.hpp index 3b19de6881..43ab1c2012 100644 --- a/drape/overlay_handle.hpp +++ b/drape/overlay_handle.hpp @@ -144,6 +144,12 @@ public: void SetReady(bool isReady) { m_isReady = isReady; } bool IsReady() const { return m_isReady; } + void SetDisplayFlag(bool display) { m_displayFlag = display; } + bool GetDisplayFlag() const { return m_displayFlag; } + + void SetUserMarkOverlay(bool isUserMarkOverlay) { m_isUserMarkOverlay = isUserMarkOverlay; } + bool IsUserMarkOverlay() const { return m_isUserMarkOverlay; } + #ifdef DEBUG_OVERLAYS_OUTPUT virtual std::string GetOverlayDebugInfo() { return ""; } #endif @@ -187,6 +193,8 @@ private: mutable bool m_extendedRectDirty; bool m_isReady = false; + bool m_isUserMarkOverlay = false; + bool m_displayFlag = false; }; class SquareHandle : public OverlayHandle diff --git a/drape/overlay_tree.cpp b/drape/overlay_tree.cpp index d4f791b2b4..9ee348469d 100644 --- a/drape/overlay_tree.cpp +++ b/drape/overlay_tree.cpp @@ -3,8 +3,7 @@ #include "drape/constants.hpp" #include "drape/debug_rect_renderer.hpp" -#include "std/algorithm.hpp" -#include "std/bind.hpp" +#include namespace dp { @@ -17,7 +16,7 @@ namespace class HandleComparator { public: - HandleComparator(bool enableMask) + explicit HandleComparator(bool enableMask) : m_enableMask(enableMask) {} @@ -28,56 +27,45 @@ public: bool IsGreater(ref_ptr const & l, ref_ptr const & r) const { - uint64_t const mask = m_enableMask ? l->GetPriorityMask() & r->GetPriorityMask() : - dp::kPriorityMaskAll; - uint64_t const priorityLeft = l->GetPriority() & mask; - uint64_t const priorityRight = r->GetPriority() & mask; - if (priorityLeft > priorityRight) + bool const displayFlagLeft = (l->IsUserMarkOverlay() ? true : l->GetDisplayFlag()); + bool const displayFlagRight = (r->IsUserMarkOverlay() ? true : r->GetDisplayFlag()); + if (displayFlagLeft > displayFlagRight) return true; - if (priorityLeft == priorityRight) + if (displayFlagLeft == displayFlagRight) { - auto const & hashLeft = l->GetOverlayID(); - auto const & hashRight = r->GetOverlayID(); - - if (hashLeft > hashRight) + uint64_t const mask = m_enableMask ? l->GetPriorityMask() & r->GetPriorityMask() : + dp::kPriorityMaskAll; + uint64_t const priorityLeft = l->GetPriority() & mask; + uint64_t const priorityRight = r->GetPriority() & mask; + if (priorityLeft > priorityRight) return true; - if (hashLeft == hashRight) - return l.get() > r.get(); - } + if (priorityLeft == priorityRight) + { + auto const & hashLeft = l->GetOverlayID(); + auto const & hashRight = r->GetOverlayID(); + if (hashLeft > hashRight) + return true; + + if (hashLeft == hashRight) + return l.get() > r.get(); + } + } return false; } private: bool m_enableMask; }; - -void StoreDisplacementInfo(ScreenBase const & modelView, int caseIndex, - ref_ptr displacingHandle, - ref_ptr displacedHandle, - OverlayTree::TDisplacementInfo & displacementInfo) -{ -#ifdef DEBUG_OVERLAYS_OUTPUT - LOG(LINFO, ("Displace (", caseIndex, "):", displacingHandle->GetOverlayDebugInfo(), - "->", displacedHandle->GetOverlayDebugInfo())); -#else - UNUSED_VALUE(caseIndex); -#endif - - if (!dp::DebugRectRenderer::Instance().IsEnabled()) - return; - displacementInfo.emplace_back(displacingHandle->GetExtendedPixelRect(modelView).Center(), - displacedHandle->GetExtendedPixelRect(modelView).Center(), - dp::Color(0, 0, 255, 255)); -} } // namespace -OverlayTree::OverlayTree() +OverlayTree::OverlayTree(double visualScale) : m_frameCounter(kInvalidFrame) , m_isDisplacementEnabled(true) { + m_traits.SetVisualScale(visualScale); for (size_t i = 0; i < m_handles.size(); i++) m_handles[i].reserve(kAverageHandlesCount[i]); } @@ -89,6 +77,7 @@ void OverlayTree::Clear() m_handlesCache.clear(); for (auto & handles : m_handles) handles.clear(); + m_displacers.clear(); } bool OverlayTree::Frame() @@ -113,7 +102,7 @@ void OverlayTree::StartOverlayPlacing(ScreenBase const & screen) ASSERT(IsNeedUpdate(), ()); TBase::Clear(); m_handlesCache.clear(); - m_traits.m_modelView = screen; + m_traits.SetModelView(screen); m_displacementInfo.clear(); } @@ -150,28 +139,15 @@ void OverlayTree::Add(ref_ptr handle) handle->SetReady(true); } - // Clip handles which are out of screen. - double const kScreenRectScale = 1.2; + // Clip handles which are out of screen if these handles were not displacers + // last time. Also clip all handles in reserve projection. m2::RectD const pixelRect = handle->GetExtendedPixelRect(modelView); - if (modelView.isPerspective()) + if (modelView.IsReverseProjection3d(pixelRect.Center()) || + (m_displacers.find(handle) == m_displacers.end() && + !m_traits.GetExtendedScreenRect().IsIntersect(pixelRect))) { - m2::RectD screenRect = modelView.PixelRectIn3d(); - screenRect.Scale(kScreenRectScale); - if (!screenRect.IsIntersect(pixelRect) || modelView.IsReverseProjection3d(pixelRect.Center())) - { - handle->SetIsVisible(false); - return; - } - } - else - { - m2::RectD screenRect = modelView.PixelRect(); - screenRect.Scale(kScreenRectScale); - if (!screenRect.IsIntersect(pixelRect)) - { - handle->SetIsVisible(false); - return; - } + handle->SetIsVisible(false); + return; } ASSERT_GREATER_OR_EQUAL(handle->GetOverlayRank(), 0, ()); @@ -248,9 +224,9 @@ void OverlayTree::InsertHandle(ref_ptr handle, int currentRank, if (boundToParent) { DeleteHandleWithParents(parentOverlay, currentRank - 1); - StoreDisplacementInfo(modelView, 0 /* case index */, handle, parentOverlay, m_displacementInfo); + StoreDisplacementInfo(0 /* case index */, handle, parentOverlay); } - StoreDisplacementInfo(modelView, 1 /* case index */, rivalHandle, handle, m_displacementInfo); + StoreDisplacementInfo(1 /* case index */, rivalHandle, handle); return; } } @@ -267,7 +243,7 @@ void OverlayTree::InsertHandle(ref_ptr handle, int currentRank, if ((*it)->GetOverlayID() == rivalHandle->GetOverlayID()) { Erase(*it); - StoreDisplacementInfo(modelView, 2 /* case index */, handle, *it, m_displacementInfo); + StoreDisplacementInfo(2 /* case index */, handle, *it); it = m_handlesCache.erase(it); } else @@ -279,7 +255,7 @@ void OverlayTree::InsertHandle(ref_ptr handle, int currentRank, else { DeleteHandle(rivalHandle); - StoreDisplacementInfo(modelView, 3 /* case index */, handle, rivalHandle, m_displacementInfo); + StoreDisplacementInfo(3 /* case index */, handle, rivalHandle); } } @@ -291,6 +267,8 @@ void OverlayTree::EndOverlayPlacing() { ASSERT(IsNeedUpdate(), ()); + m_displacers.clear(); + #ifdef DEBUG_OVERLAYS_OUTPUT LOG(LINFO, ("- BEGIN OVERLAYS PLACING")); #endif @@ -311,10 +289,15 @@ void OverlayTree::EndOverlayPlacing() } for (int rank = 0; rank < dp::OverlayRanksCount; rank++) + { + for (auto const & handle : m_handles[rank]) + handle->SetDisplayFlag(false); m_handles[rank].clear(); + } for (auto const & handle : m_handlesCache) { + handle->SetDisplayFlag(true); handle->SetIsVisible(true); handle->SetCachingEnable(false); } @@ -387,7 +370,7 @@ bool OverlayTree::GetSelectedFeatureRect(ScreenBase const & screen, m2::RectD & void OverlayTree::Select(m2::PointD const & glbPoint, TOverlayContainer & result) const { - ScreenBase const & screen = m_traits.m_modelView; + ScreenBase const & screen = GetModelView(); m2::PointD const pxPoint = screen.GtoP(glbPoint); double const kSearchRectHalfSize = 10.0; @@ -403,7 +386,7 @@ void OverlayTree::Select(m2::PointD const & glbPoint, TOverlayContainer & result void OverlayTree::Select(m2::RectD const & rect, TOverlayContainer & result) const { - ScreenBase screen = m_traits.m_modelView; + ScreenBase screen = GetModelView(); ForEachInRect(rect, [&](ref_ptr const & h) { if (!h->HasLinearFeatureShape() && h->IsVisible() && h->GetOverlayID().m_featureId.IsValid()) @@ -437,4 +420,49 @@ OverlayTree::TDisplacementInfo const & OverlayTree::GetDisplacementInfo() const { return m_displacementInfo; } + +void OverlayTree::StoreDisplacementInfo(int caseIndex, ref_ptr displacerHandle, + ref_ptr displacedHandle) +{ + ScreenBase const & modelView = GetModelView(); + m2::RectD const pixelRect = displacerHandle->GetExtendedPixelRect(modelView); + if (!m_traits.GetDisplacersFreeRect().IsRectInside(pixelRect)) + m_displacers.insert(displacerHandle); + +#ifdef DEBUG_OVERLAYS_OUTPUT + LOG(LINFO, ("Displace (", caseIndex, "):", displacerHandle->GetOverlayDebugInfo(), + "->", displacedHandle->GetOverlayDebugInfo())); +#else + UNUSED_VALUE(caseIndex); +#endif + + if (!dp::DebugRectRenderer::Instance().IsEnabled()) + return; + m_displacementInfo.emplace_back(displacerHandle->GetExtendedPixelRect(modelView).Center(), + displacedHandle->GetExtendedPixelRect(modelView).Center(), + dp::Color(0, 0, 255, 255)); +} + +void detail::OverlayTraits::SetVisualScale(double visualScale) +{ + m_visualScale = visualScale; +} + +void detail::OverlayTraits::SetModelView(ScreenBase const & modelView) +{ + m_modelView = modelView; + + double const extension = m_visualScale * kScreenPixelRectExtension; + double const doubleExtension = 2.0 * extension; + m2::RectD screenRect = modelView.isPerspective() ? modelView.PixelRectIn3d() + : modelView.PixelRect(); + m_extendedScreenRect = screenRect; + m_extendedScreenRect.Inflate(extension, extension); + + m_displacersFreeRect = screenRect; + if (m_displacersFreeRect.SizeX() > doubleExtension && m_displacersFreeRect.SizeY() > doubleExtension) + m_displacersFreeRect.Inflate(-extension, -extension); + else + m_displacersFreeRect.SetSizes(1e-7, 1e-7); +} } // namespace dp diff --git a/drape/overlay_tree.hpp b/drape/overlay_tree.hpp index 42348a491c..a56b4cbf8b 100644 --- a/drape/overlay_tree.hpp +++ b/drape/overlay_tree.hpp @@ -8,27 +8,39 @@ #include "base/buffer_vector.hpp" -#include "std/array.hpp" -#include "std/vector.hpp" -#include "std/unordered_set.hpp" +#include +#include +#include +#include namespace dp { namespace detail { -struct OverlayTraits +class OverlayTraits { - ScreenBase m_modelView; - - inline m2::RectD const LimitRect(ref_ptr const & handle) +public: + m2::RectD const LimitRect(ref_ptr const & handle) { return handle->GetExtendedPixelRect(m_modelView); } + ScreenBase const & GetModelView() const { return m_modelView; } + m2::RectD const & GetExtendedScreenRect() const { return m_extendedScreenRect; } + m2::RectD const & GetDisplacersFreeRect() const { return m_displacersFreeRect; } + + void SetVisualScale(double visualScale); + void SetModelView(ScreenBase const & modelView); + +private: + double m_visualScale; + ScreenBase m_modelView; + m2::RectD m_extendedScreenRect; + m2::RectD m_displacersFreeRect; }; struct OverlayHasher { - hash m_hasher; + std::hash m_hasher; size_t operator()(ref_ptr const & handle) const { @@ -44,9 +56,9 @@ class OverlayTree : public m4::Tree, detail::OverlayTrait using TBase = m4::Tree, detail::OverlayTraits>; public: - using HandlesCache = unordered_set, detail::OverlayHasher>; + using HandlesCache = std::unordered_set, detail::OverlayHasher>; - OverlayTree(); + OverlayTree(double visualScale); void Clear(); bool Frame(); @@ -81,7 +93,7 @@ public: TDisplacementInfo const & GetDisplacementInfo() const; private: - ScreenBase const & GetModelView() const { return m_traits.m_modelView; } + ScreenBase const & GetModelView() const { return m_traits.GetModelView(); } void InsertHandle(ref_ptr handle, int currentRank, ref_ptr const & parentOverlay); bool CheckHandle(ref_ptr handle, int currentRank, @@ -91,8 +103,10 @@ private: ref_ptr FindParent(ref_ptr handle, int searchingRank) const; void DeleteHandleWithParents(ref_ptr handle, int currentRank); + void StoreDisplacementInfo(int caseIndex, ref_ptr displacerHandle, + ref_ptr displacedHandle); int m_frameCounter; - array>, dp::OverlayRanksCount> m_handles; + std::array>, dp::OverlayRanksCount> m_handles; HandlesCache m_handlesCache; bool m_isDisplacementEnabled; @@ -100,5 +114,7 @@ private: FeatureID m_selectedFeatureID; TDisplacementInfo m_displacementInfo; + + HandlesCache m_displacers; }; } // namespace dp diff --git a/drape_frontend/CMakeLists.txt b/drape_frontend/CMakeLists.txt index 3fd99afa8f..83b3587fc5 100644 --- a/drape_frontend/CMakeLists.txt +++ b/drape_frontend/CMakeLists.txt @@ -113,7 +113,6 @@ set( gui/shape.hpp gui/skin.cpp gui/skin.hpp - intrusive_vector.hpp kinetic_scroller.cpp kinetic_scroller.hpp line_shape.cpp diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index 92fd09af9f..7702640e43 100755 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -166,7 +166,6 @@ HEADERS += \ frontend_renderer.hpp \ gps_track_point.hpp \ gps_track_renderer.hpp \ - intrusive_vector.hpp \ line_shape.hpp \ line_shape_helper.hpp \ map_data_provider.hpp \ diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 8a84e6bae3..2b17e71d28 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -118,7 +118,7 @@ FrontendRenderer::FrontendRenderer(Params && params) , m_gpuProgramManager(new dp::GpuProgramManager()) , m_trafficRenderer(new TrafficRenderer()) , m_drapeApiRenderer(new DrapeApiRenderer()) - , m_overlayTree(new dp::OverlayTree()) + , m_overlayTree(new dp::OverlayTree(VisualParams::Instance().GetVisualScale())) , m_enablePerspectiveInNavigation(false) , m_enable3dBuildings(params.m_allow3dBuildings) , m_isIsometry(false) @@ -1655,7 +1655,10 @@ bool FrontendRenderer::OnNewVisibleViewport(m2::RectD const & oldViewport, TTilesCollection FrontendRenderer::ResolveTileKeys(ScreenBase const & screen) { - m2::RectD const & rect = screen.ClipRect(); + m2::RectD rect = screen.ClipRect(); + double const vs = VisualParams::Instance().GetVisualScale(); + double const extension = vs * dp::kScreenPixelRectExtension * screen.GetScale(); + rect.Inflate(extension, extension); int const dataZoomLevel = ClipTileZoomByMaxDataZoom(m_currentZoomLevel); m_notFinishedTiles.clear(); @@ -1663,8 +1666,8 @@ TTilesCollection FrontendRenderer::ResolveTileKeys(ScreenBase const & screen) // Request new tiles. TTilesCollection tiles; buffer_vector tilesToDelete; - CoverageResult result = CalcTilesCoverage(rect, dataZoomLevel, - [this, &rect, &tiles, &tilesToDelete](int tileX, int tileY) + auto result = CalcTilesCoverage(rect, dataZoomLevel, + [this, &rect, &tiles, &tilesToDelete](int tileX, int tileY) { TileKey const key(tileX, tileY, m_currentZoomLevel); if (rect.IsIntersect(key.GetGlobalRect())) diff --git a/drape_frontend/intrusive_vector.hpp b/drape_frontend/intrusive_vector.hpp deleted file mode 100644 index d80aac10b3..0000000000 --- a/drape_frontend/intrusive_vector.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "base/assert.hpp" - -#include "std/cstdint.hpp" - -namespace df -{ - -enum FillDirection -{ - Forward, - Backward -}; - -template -class IntrusiveVector -{ -public: - IntrusiveVector(void * memoryBuffer, uint32_t byteCount) - : m_memory(reinterpret_cast(memoryBuffer)) - , m_direction(Forward) - { - ASSERT(byteCount % sizeof(T) == 0, ()); - m_capacity = byteCount / sizeof(T); - m_size = 0; - } - - void SetFillDirection(FillDirection direction) - { - ASSERT(m_size == 0, ()); - m_direction = direction; - } - - void PushBack(T const & value) - { - ASSERT(m_size < m_capacity, ()); - if (m_direction == Forward) - m_memory[m_size++] = value; - else - { - m_memory[m_capacity - m_size - 1] = value; - m_size++; - } - } - -private: - T * m_memory; - FillDirection m_direction; - uint32_t m_capacity; - uint32_t m_size; -}; - -} diff --git a/drape_frontend/my_position.cpp b/drape_frontend/my_position.cpp index 214653b0e1..eaf756ad5a 100644 --- a/drape_frontend/my_position.cpp +++ b/drape_frontend/my_position.cpp @@ -134,7 +134,7 @@ void MyPosition::RenderMyPosition(ScreenBase const & screen, int zoomLevel, uniforms.SetMatrix4x4Value("modelView", mv.m_data); m2::PointD const pos = MapShape::ConvertToLocal(m_position, key.GetGlobalRect().Center(), kShapeCoordScalar); - uniforms.SetFloatValue("u_position", pos.x, pos.y, dp::depth::MY_POSITION_MARK); + uniforms.SetFloatValue("u_position", pos.x, pos.y, dp::depth::kMyPositionMarkDepth); uniforms.SetFloatValue("u_azimut", -(m_azimuth + screen.GetAngle())); uniforms.SetFloatValue("u_opacity", 1.0); RenderPart(mng, uniforms, MY_POSITION_POINT); diff --git a/drape_frontend/path_text_shape.cpp b/drape_frontend/path_text_shape.cpp index 7271484017..f426dd36a6 100644 --- a/drape_frontend/path_text_shape.cpp +++ b/drape_frontend/path_text_shape.cpp @@ -1,5 +1,4 @@ #include "drape_frontend/path_text_shape.hpp" -#include "drape_frontend/intrusive_vector.hpp" #include "drape_frontend/shader_def.hpp" #include "drape_frontend/text_handle.hpp" diff --git a/drape_frontend/poi_symbol_shape.cpp b/drape_frontend/poi_symbol_shape.cpp index a292acf5d0..9fcf914501 100644 --- a/drape_frontend/poi_symbol_shape.cpp +++ b/drape_frontend/poi_symbol_shape.cpp @@ -155,6 +155,8 @@ drape_ptr PoiSymbolShape::CreateOverlayHandle(m2::PointF cons true /* isBillboard */); handle->SetPivotZ(m_params.m_posZ); handle->SetExtendingSize(m_params.m_extendingSize); + if (m_params.m_specialDisplacement == SpecialDisplacement::UserMark) + handle->SetUserMarkOverlay(true); return handle; } diff --git a/drape_frontend/render_group.cpp b/drape_frontend/render_group.cpp index 021360629e..8285aa696a 100755 --- a/drape_frontend/render_group.cpp +++ b/drape_frontend/render_group.cpp @@ -53,7 +53,7 @@ void RenderGroup::Update(ScreenBase const & modelView) { ASSERT(m_shader != nullptr, ()); ASSERT(m_generalUniforms != nullptr, ()); - for(drape_ptr & renderBucket : m_renderBuckets) + for (auto & renderBucket : m_renderBuckets) renderBucket->Update(modelView); } diff --git a/drape_frontend/text_layout.hpp b/drape_frontend/text_layout.hpp index 2a82ba1cab..e22fb15b59 100644 --- a/drape_frontend/text_layout.hpp +++ b/drape_frontend/text_layout.hpp @@ -1,7 +1,6 @@ #pragma once #include "drape_frontend/shape_view_params.hpp" -#include "drape_frontend/intrusive_vector.hpp" #include "drape/utils/vertex_decl.hpp" #include "drape/glsl_types.hpp" diff --git a/drape_frontend/text_shape.cpp b/drape_frontend/text_shape.cpp index 4856d8f1d7..709074b0aa 100644 --- a/drape_frontend/text_shape.cpp +++ b/drape_frontend/text_shape.cpp @@ -301,6 +301,8 @@ void TextShape::DrawSubStringPlain(StraightTextLayout const & layout, dp::FontDe handle->SetOverlayRank(m_hasPOI ? (isPrimary ? dp::OverlayRank1 : dp::OverlayRank2) : dp::OverlayRank0); handle->SetExtendingSize(m_params.m_extendingSize); + if (m_params.m_specialDisplacement == SpecialDisplacement::UserMark) + handle->SetUserMarkOverlay(true); dp::AttributeProvider provider(2, static_cast(staticBuffer.size())); provider.InitStream(0, gpu::TextStaticVertex::GetBindingInfo(), make_ref(staticBuffer.data()));