From 7a58e9f450e8aebedc0f04618a8ce5820d18191d Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Tue, 22 Nov 2016 13:43:35 +0300 Subject: [PATCH] Refactored traffic rendering --- drape_frontend/apply_feature_functors.cpp | 5 + drape_frontend/apply_feature_functors.hpp | 3 + drape_frontend/backend_renderer.cpp | 43 +++-- drape_frontend/backend_renderer.hpp | 5 +- drape_frontend/drape_engine.cpp | 10 +- drape_frontend/drape_engine.hpp | 5 +- drape_frontend/engine_context.cpp | 5 + drape_frontend/engine_context.hpp | 2 + drape_frontend/frontend_renderer.cpp | 21 ++- drape_frontend/message.hpp | 3 +- drape_frontend/message_subclasses.hpp | 36 +++- drape_frontend/read_manager.cpp | 14 +- drape_frontend/read_manager.hpp | 6 +- drape_frontend/rule_drawer.cpp | 58 +++++- drape_frontend/rule_drawer.hpp | 7 +- drape_frontend/tile_info.cpp | 3 +- drape_frontend/tile_info.hpp | 4 + drape_frontend/traffic_generator.cpp | 212 ++++++++++------------ drape_frontend/traffic_generator.hpp | 47 +++-- drape_frontend/traffic_renderer.cpp | 63 +++++-- drape_frontend/traffic_renderer.hpp | 7 +- geometry/polyline2d.hpp | 2 +- map/framework.cpp | 20 +- map/framework.hpp | 3 + map/traffic_manager.cpp | 95 ++-------- map/traffic_manager.hpp | 9 +- 26 files changed, 391 insertions(+), 297 deletions(-) diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp index 74688951a0..802a6b874a 100644 --- a/drape_frontend/apply_feature_functors.cpp +++ b/drape_frontend/apply_feature_functors.cpp @@ -802,4 +802,9 @@ void ApplyLineFeature::Finish() } } +m2::PolylineD ApplyLineFeature::GetPolyline() const +{ + return HasGeometry() ? m2::PolylineD(m_spline->GetPath()) : m2::PolylineD(); +} + } // namespace df diff --git a/drape_frontend/apply_feature_functors.hpp b/drape_frontend/apply_feature_functors.hpp index a88792e0e4..b52b20fe9d 100644 --- a/drape_frontend/apply_feature_functors.hpp +++ b/drape_frontend/apply_feature_functors.hpp @@ -9,6 +9,7 @@ #include "indexer/point_to_int64.hpp" #include "geometry/point2d.hpp" +#include "geometry/polyline2d.hpp" #include "geometry/spline.hpp" #include "std/unordered_map.hpp" @@ -144,6 +145,8 @@ public: void ProcessRule(Stylist::TRuleWrapper const & rule); void Finish(); + m2::PolylineD GetPolyline() const; + private: m2::SharedSpline m_spline; vector m_clippedSplines; diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 396b5cb5e4..c3e187c372 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -27,7 +27,8 @@ namespace df BackendRenderer::BackendRenderer(Params const & params) : BaseRenderer(ThreadsCommutator::ResourceUploadThread, params) , m_model(params.m_model) - , m_readManager(make_unique_dp(params.m_commutator, m_model, params.m_allow3dBuildings)) + , m_readManager(make_unique_dp(params.m_commutator, m_model, + params.m_allow3dBuildings, params.m_trafficEnabled)) , m_trafficGenerator(make_unique_dp(bind(&BackendRenderer::FlushTrafficRenderData, this, _1))) , m_requestedTiles(params.m_requestedTiles) , m_updateCurrentCountryFn(params.m_updateCurrentCountryFn) @@ -331,36 +332,38 @@ void BackendRenderer::AcceptMessage(ref_ptr message) break; } - case Message::CacheTrafficSegments: + case Message::EnableTraffic: { - ref_ptr msg = message; - m_trafficGenerator->AddSegmentsGeometry(msg->GetSegments()); + ref_ptr msg = message; + m_readManager->SetTrafficEnabled(msg->IsTrafficEnabled()); + m_commutator->PostMessage(ThreadsCommutator::RenderThread, + make_unique_dp(msg->IsTrafficEnabled()), + MessagePriority::Normal); + break; + } + + case Message::FlushTrafficGeometry: + { + ref_ptr msg = message; + m_trafficGenerator->FlushSegmentsGeometry(msg->GetKey(), msg->GetSegments(), m_texMng); break; } case Message::UpdateTraffic: { ref_ptr msg = message; - auto segments = m_trafficGenerator->GetSegmentsToUpdate(msg->GetSegmentsColoring()); - if (!segments.empty()) + bool const needInvalidate = m_trafficGenerator->UpdateColoring(msg->GetSegmentsColoring()); + if (m_trafficGenerator->IsColorsCacheRefreshed()) { + auto texCoords = m_trafficGenerator->ProcessCacheRefreshing(); m_commutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(segments), + make_unique_dp(move(texCoords)), MessagePriority::Normal); } - - if (segments.size() < msg->GetSegmentsColoring().size()) - { - m_trafficGenerator->GetTrafficGeom(m_texMng, msg->GetSegmentsColoring()); - - if (m_trafficGenerator->IsColorsCacheRefreshed()) - { - auto texCoords = m_trafficGenerator->ProcessCacheRefreshing(); - m_commutator->PostMessage(ThreadsCommutator::RenderThread, - make_unique_dp(move(texCoords)), - MessagePriority::Normal); - } - } + m_commutator->PostMessage(ThreadsCommutator::RenderThread, + make_unique_dp(move(msg->GetSegmentsColoring()), + needInvalidate), + MessagePriority::Normal); break; } case Message::ClearTrafficData: diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp index 6f8f08796e..15d138e0a3 100644 --- a/drape_frontend/backend_renderer.hpp +++ b/drape_frontend/backend_renderer.hpp @@ -38,18 +38,21 @@ public: Params(ref_ptr commutator, ref_ptr factory, ref_ptr texMng, MapDataProvider const & model, TUpdateCurrentCountryFn const & updateCurrentCountryFn, - ref_ptr requestedTiles, bool allow3dBuildings) + ref_ptr requestedTiles, bool allow3dBuildings, + bool trafficEnabled) : BaseRenderer::Params(commutator, factory, texMng) , m_model(model) , m_updateCurrentCountryFn(updateCurrentCountryFn) , m_requestedTiles(requestedTiles) , m_allow3dBuildings(allow3dBuildings) + , m_trafficEnabled(trafficEnabled) {} MapDataProvider const & m_model; TUpdateCurrentCountryFn m_updateCurrentCountryFn; ref_ptr m_requestedTiles; bool m_allow3dBuildings; + bool m_trafficEnabled; }; BackendRenderer(Params const & params); diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 782bfcc390..d81085387e 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -71,7 +71,8 @@ DrapeEngine::DrapeEngine(Params && params) BackendRenderer::Params brParams(frParams.m_commutator, frParams.m_oglContextFactory, frParams.m_texMng, params.m_model, params.m_model.UpdateCurrentCountryFn(), - make_ref(m_requestedTiles), params.m_allow3dBuildings); + make_ref(m_requestedTiles), params.m_allow3dBuildings, + params.m_trafficEnabled); m_backend = make_unique_dp(brParams); m_widgetsInfo = move(params.m_info); @@ -533,13 +534,10 @@ void DrapeEngine::RequestSymbolsSize(vector const & symbols, MessagePriority::Normal); } -void DrapeEngine::CacheTrafficSegmentsGeometry(TrafficSegmentsGeometry const & segments) +void DrapeEngine::EnableTraffic(bool trafficEnabled) { - if (segments.empty()) - return; - m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread, - make_unique_dp(segments), + make_unique_dp(trafficEnabled), MessagePriority::Normal); } diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 00d5445224..ec90aea5f5 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -44,6 +44,7 @@ public: gui::TWidgetsInitInfo && info, pair const & initialMyPositionMode, bool allow3dBuildings, + bool trafficEnabled, bool blockTapEvents, bool showChoosePositionMark, vector && boundAreaTriangles, @@ -58,6 +59,7 @@ public: , m_info(move(info)) , m_initialMyPositionMode(initialMyPositionMode) , m_allow3dBuildings(allow3dBuildings) + , m_trafficEnabled(trafficEnabled) , m_blockTapEvents(blockTapEvents) , m_showChoosePositionMark(showChoosePositionMark) , m_boundAreaTriangles(move(boundAreaTriangles)) @@ -74,6 +76,7 @@ public: gui::TWidgetsInitInfo m_info; pair m_initialMyPositionMode; bool m_allow3dBuildings; + bool m_trafficEnabled; bool m_blockTapEvents; bool m_showChoosePositionMark; vector m_boundAreaTriangles; @@ -162,7 +165,7 @@ public: void RequestSymbolsSize(vector const & symbols, TRequestSymbolsSizeCallback const & callback); - void CacheTrafficSegmentsGeometry(TrafficSegmentsGeometry const & segments); + void EnableTraffic(bool trafficEnabled); void UpdateTraffic(TrafficSegmentsColoring const & segmentsColoring); void ClearTrafficCache(MwmSet::MwmId const & mwmId); diff --git a/drape_frontend/engine_context.cpp b/drape_frontend/engine_context.cpp index 3f6ac8cc97..ff864cf128 100644 --- a/drape_frontend/engine_context.cpp +++ b/drape_frontend/engine_context.cpp @@ -35,6 +35,11 @@ void EngineContext::FlushOverlays(TMapShapes && shapes) PostMessage(make_unique_dp(m_tileKey, move(shapes))); } +void EngineContext::FlushTrafficGeometry(TrafficSegmentsGeometry && geometry) +{ + PostMessage(make_unique_dp(m_tileKey, move(geometry))); +} + void EngineContext::EndReadTile() { PostMessage(make_unique_dp(m_tileKey)); diff --git a/drape_frontend/engine_context.hpp b/drape_frontend/engine_context.hpp index 54a66dd12c..febfc6189a 100644 --- a/drape_frontend/engine_context.hpp +++ b/drape_frontend/engine_context.hpp @@ -3,6 +3,7 @@ #include "drape_frontend/map_shape.hpp" #include "drape_frontend/tile_utils.hpp" #include "drape_frontend/threads_commutator.hpp" +#include "drape_frontend/traffic_generator.hpp" #include "drape/pointers.hpp" @@ -29,6 +30,7 @@ public: void BeginReadTile(); void Flush(TMapShapes && shapes); void FlushOverlays(TMapShapes && shapes); + void FlushTrafficGeometry(TrafficSegmentsGeometry && geometry); void EndReadTile(); private: diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index fa99a26b2c..b7b9bdd8de 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -290,9 +290,11 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) } } } - if (changed) UpdateCanBeDeletedStatus(); + + if (m_notFinishedTiles.empty()) + m_trafficRenderer->OnGeometryReady(m_currentZoomLevel); break; } @@ -739,10 +741,23 @@ void FrontendRenderer::AcceptMessage(ref_ptr message) break; } + case Message::EnableTraffic: + { + ref_ptr msg = message; + if (msg->IsTrafficEnabled()) + InvalidateRect(m_userEventStream.GetCurrentScreen().ClipRect()); + else + m_trafficRenderer->ClearGLDependentResources(); + break; + } + case Message::UpdateTraffic: { ref_ptr msg = message; - m_trafficRenderer->UpdateTraffic(msg->GetSegmentsColoring()); + if (msg->NeedInvalidate()) + InvalidateRect(m_userEventStream.GetCurrentScreen().ClipRect()); + else + m_trafficRenderer->UpdateTraffic(msg->GetSegmentsColoring()); break; } @@ -1584,6 +1599,8 @@ TTilesCollection FrontendRenderer::ResolveTileKeys(ScreenBase const & screen) return group->GetTileKey().m_zoomLevel != m_currentZoomLevel; }); + m_trafficRenderer->OnUpdateViewport(result, m_currentZoomLevel, tilesToDelete); + return tiles; } diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp index 6c9cd7a07c..19d4850a08 100644 --- a/drape_frontend/message.hpp +++ b/drape_frontend/message.hpp @@ -65,7 +65,8 @@ public: RequestSymbolsSize, RecoverGLResources, SetVisibleViewport, - CacheTrafficSegments, + EnableTraffic, + FlushTrafficGeometry, SetTrafficTexCoords, UpdateTraffic, FlushTrafficData, diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp index 3ac7db418c..db3b2645b3 100644 --- a/drape_frontend/message_subclasses.hpp +++ b/drape_frontend/message_subclasses.hpp @@ -996,16 +996,32 @@ private: TRequestSymbolsSizeCallback m_callback; }; -class CacheTrafficSegmentsMessage : public Message +class EnableTrafficMessage : public Message { public: - explicit CacheTrafficSegmentsMessage(TrafficSegmentsGeometry const & segments) - : m_segments(segments) + explicit EnableTrafficMessage(bool trafficEnabled) + : m_trafficEnabled(trafficEnabled) {} - Type GetType() const override { return Message::CacheTrafficSegments; } + Type GetType() const override { return Message::EnableTraffic; } - TrafficSegmentsGeometry const & GetSegments() const { return m_segments; } + bool IsTrafficEnabled() const { return m_trafficEnabled; } + +private: + bool const m_trafficEnabled; +}; + +class FlushTrafficGeometryMessage : public BaseTileMessage +{ +public: + FlushTrafficGeometryMessage(TileKey const & tileKey, TrafficSegmentsGeometry && segments) + : BaseTileMessage(tileKey) + , m_segments(move(segments)) + {} + + Type GetType() const override { return Message::FlushTrafficGeometry; } + + TrafficSegmentsGeometry & GetSegments() { return m_segments; } private: TrafficSegmentsGeometry m_segments; @@ -1032,15 +1048,23 @@ class UpdateTrafficMessage : public Message public: explicit UpdateTrafficMessage(TrafficSegmentsColoring const & segmentsColoring) : m_segmentsColoring(segmentsColoring) + , m_needInvalidate(false) + {} + + UpdateTrafficMessage(TrafficSegmentsColoring const & segmentsColoring, bool needInvalidate) + : m_segmentsColoring(segmentsColoring) + , m_needInvalidate(needInvalidate) {} Type GetType() const override { return Message::UpdateTraffic; } bool IsGLContextDependent() const override { return true; } - TrafficSegmentsColoring const & GetSegmentsColoring() const { return m_segmentsColoring; } + TrafficSegmentsColoring & GetSegmentsColoring() { return m_segmentsColoring; } + bool NeedInvalidate() const { return m_needInvalidate; } private: TrafficSegmentsColoring m_segmentsColoring; + bool const m_needInvalidate; }; class FlushTrafficDataMessage : public Message diff --git a/drape_frontend/read_manager.cpp b/drape_frontend/read_manager.cpp index e8a50861e6..a8fcae7570 100755 --- a/drape_frontend/read_manager.cpp +++ b/drape_frontend/read_manager.cpp @@ -36,12 +36,14 @@ struct LessCoverageCell } // namespace -ReadManager::ReadManager(ref_ptr commutator, MapDataProvider & model, bool allow3dBuildings) +ReadManager::ReadManager(ref_ptr commutator, MapDataProvider & model, + bool allow3dBuildings, bool trafficEnabled) : m_commutator(commutator) , m_model(model) , m_pool(make_unique_dp(ReadCount(), bind(&ReadManager::OnTaskFinished, this, _1))) , m_have3dBuildings(false) , m_allow3dBuildings(allow3dBuildings) + , m_trafficEnabled(trafficEnabled) , m_modeChanged(false) , myPool(64, ReadMWMTaskFactory(m_model)) , m_counter(0) @@ -202,6 +204,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_have3dBuildings && m_allow3dBuildings); + tileInfo->SetTrafficEnabled(m_trafficEnabled); m_tileInfos.insert(tileInfo); ReadMWMTask * task = myPool.Get(); @@ -267,4 +270,13 @@ void ReadManager::Allow3dBuildings(bool allow3dBuildings) } } +void ReadManager::SetTrafficEnabled(bool trafficEnabled) +{ + if (m_trafficEnabled != trafficEnabled) + { + m_modeChanged = true; + m_trafficEnabled = trafficEnabled; + } +} + } // namespace df diff --git a/drape_frontend/read_manager.hpp b/drape_frontend/read_manager.hpp index 22eb7119da..b4ea123851 100755 --- a/drape_frontend/read_manager.hpp +++ b/drape_frontend/read_manager.hpp @@ -27,7 +27,8 @@ class CoverageUpdateDescriptor; class ReadManager { public: - ReadManager(ref_ptr commutator, MapDataProvider & model, bool allow3dBuildings); + ReadManager(ref_ptr commutator, MapDataProvider & model, + bool allow3dBuildings, bool trafficEnabled); void UpdateCoverage(ScreenBase const & screen, bool have3dBuildings, TTilesCollection const & tiles, ref_ptr texMng); @@ -38,6 +39,8 @@ public: bool CheckTileKey(TileKey const & tileKey) const; void Allow3dBuildings(bool allow3dBuildings); + void SetTrafficEnabled(bool trafficEnabled); + static size_t ReadCount(); private: @@ -56,6 +59,7 @@ private: ScreenBase m_currentViewport; bool m_have3dBuildings; bool m_allow3dBuildings; + bool m_trafficEnabled; bool m_modeChanged; struct LessByTileInfo diff --git a/drape_frontend/rule_drawer.cpp b/drape_frontend/rule_drawer.cpp index ce9fa8fe10..2d7a3c60d8 100644 --- a/drape_frontend/rule_drawer.cpp +++ b/drape_frontend/rule_drawer.cpp @@ -1,7 +1,8 @@ #include "drape_frontend/rule_drawer.hpp" -#include "drape_frontend/stylist.hpp" -#include "drape_frontend/engine_context.hpp" + #include "drape_frontend/apply_feature_functors.hpp" +#include "drape_frontend/engine_context.hpp" +#include "drape_frontend/stylist.hpp" #include "drape_frontend/visual_params.hpp" #include "indexer/feature.hpp" @@ -24,8 +25,8 @@ #include "base/string_utils.hpp" #endif -namespace { - +namespace +{ df::BaseApplyFeature::HotelData ExtractHotelData(FeatureType const & f) { df::BaseApplyFeature::HotelData result; @@ -39,7 +40,29 @@ df::BaseApplyFeature::HotelData ExtractHotelData(FeatureType const & f) return result; } -} // namespace +void ExtractTrafficGeometry(FeatureType const & f, df::RoadClass const & roadClass, m2::PolylineD const & polyline, + df::TrafficSegmentsGeometry & geometry) +{ + df::TrafficSegmentsGeometry output; + if (polyline.GetSize() < 2) + return; + + static vector directions = {traffic::TrafficInfo::RoadSegmentId::kForwardDirection, + traffic::TrafficInfo::RoadSegmentId::kReverseDirection}; + auto & segments = geometry[f.GetID().m_mwmId]; + segments.reserve(segments.size() + directions.size() * (polyline.GetPoints().size() - 1)); + for (uint16_t segmentIndex = 0; segmentIndex + 1 < static_cast(polyline.GetPoints().size()); segmentIndex++) + { + for (size_t dirIndex = 0; dirIndex < directions.size(); dirIndex++) + { + auto const sid = traffic::TrafficInfo::RoadSegmentId(f.GetID().m_index, segmentIndex, directions[dirIndex]); + bool const isReversed = (directions[dirIndex] == traffic::TrafficInfo::RoadSegmentId::kReverseDirection); + segments.emplace_back(sid, df::TrafficSegmentGeometry(polyline.ExtractSegment(segmentIndex, isReversed), roadClass)); + } + } +} + +} // namespace namespace df { @@ -47,12 +70,14 @@ namespace df RuleDrawer::RuleDrawer(TDrawerCallback const & fn, TCheckCancelledCallback const & checkCancelled, TIsCountryLoadedByNameFn const & isLoadedFn, - ref_ptr context, bool is3dBuildings) + ref_ptr context, + bool is3dBuildings, bool trafficEnabled) : m_callback(fn) , m_checkCancelled(checkCancelled) , m_isLoadedFn(isLoadedFn) , m_context(context) , m_is3dBuidings(is3dBuildings) + , m_trafficEnabled(trafficEnabled) , m_wasCancelled(false) { ASSERT(m_callback != nullptr, ()); @@ -85,6 +110,8 @@ RuleDrawer::~RuleDrawer() overlayShapes.swap(m_mapShapes[df::OverlayType]); m_context->FlushOverlays(move(overlayShapes)); } + + m_context->FlushTrafficGeometry(move(m_trafficGeometry)); } bool RuleDrawer::CheckCancelled() @@ -245,6 +272,25 @@ void RuleDrawer::operator()(FeatureType const & f) if (apply.HasGeometry()) s.ForEachRule(bind(&ApplyLineFeature::ProcessRule, &apply, _1)); apply.Finish(); + + if (m_trafficEnabled && zoomLevel >= kRoadClass0ZoomLevel) + { + auto const highwayClass = ftypes::GetHighwayClass(f); + if (highwayClass == ftypes::HighwayClass::Trunk || highwayClass == ftypes::HighwayClass::Primary) + { + ExtractTrafficGeometry(f, df::RoadClass::Class0, apply.GetPolyline(), m_trafficGeometry); + } + else if ((highwayClass == ftypes::HighwayClass::Secondary || highwayClass == ftypes::HighwayClass::Tertiary) && + zoomLevel >= kRoadClass1ZoomLevel) + { + ExtractTrafficGeometry(f, df::RoadClass::Class1, apply.GetPolyline(), m_trafficGeometry); + } + else if ((highwayClass == ftypes::HighwayClass::LivingStreet || highwayClass == ftypes::HighwayClass::Service) && + zoomLevel >= kRoadClass2ZoomLevel) + { + ExtractTrafficGeometry(f, df::RoadClass::Class2, apply.GetPolyline(), m_trafficGeometry); + } + } } else { diff --git a/drape_frontend/rule_drawer.hpp b/drape_frontend/rule_drawer.hpp index 4af2842783..4b1c9c293d 100644 --- a/drape_frontend/rule_drawer.hpp +++ b/drape_frontend/rule_drawer.hpp @@ -2,6 +2,7 @@ #include "drape_frontend/map_shape.hpp" #include "drape_frontend/tile_key.hpp" +#include "drape_frontend/traffic_generator.hpp" #include "drape/pointers.hpp" @@ -29,7 +30,8 @@ public: using TIsCountryLoadedByNameFn = function; RuleDrawer(TDrawerCallback const & drawerFn, TCheckCancelledCallback const & checkCancelled, - TIsCountryLoadedByNameFn const & isLoadedFn, ref_ptr context, bool is3dBuildings); + TIsCountryLoadedByNameFn const & isLoadedFn, ref_ptr context, + bool is3dBuildings, bool trafficEnabled); ~RuleDrawer(); void operator() (FeatureType const & f); @@ -47,6 +49,9 @@ private: bool const m_is3dBuidings; + bool const m_trafficEnabled; + TrafficSegmentsGeometry m_trafficGeometry; + array m_mapShapes; bool m_wasCancelled; }; diff --git a/drape_frontend/tile_info.cpp b/drape_frontend/tile_info.cpp index 66ae5e59c4..b8ffbc54c3 100644 --- a/drape_frontend/tile_info.cpp +++ b/drape_frontend/tile_info.cpp @@ -17,6 +17,7 @@ namespace df TileInfo::TileInfo(drape_ptr && context) : m_context(move(context)) , m_is3dBuildings(false) + , m_trafficEnabled(false) , m_isCanceled(false) { } @@ -69,7 +70,7 @@ void TileInfo::ReadFeatures(MapDataProvider const & model) RuleDrawer drawer(bind(&TileInfo::InitStylist, this, _1, _2), bind(&TileInfo::IsCancelled, this), model.m_isCountryLoadedByName, - make_ref(m_context), m_is3dBuildings); + make_ref(m_context), m_is3dBuildings, m_trafficEnabled); model.ReadFeatures(bind(ref(drawer), _1), m_featureInfo); } } diff --git a/drape_frontend/tile_info.hpp b/drape_frontend/tile_info.hpp index 3920662275..1c43d6e640 100644 --- a/drape_frontend/tile_info.hpp +++ b/drape_frontend/tile_info.hpp @@ -34,6 +34,9 @@ public: void Set3dBuildings(bool buildings3d) { m_is3dBuildings = buildings3d; } bool Get3dBuildings() const { return m_is3dBuildings; } + void SetTrafficEnabled(bool trafficEnabled) { m_trafficEnabled = trafficEnabled; } + bool GetTrafficEnabled() const { return m_trafficEnabled; } + m2::RectD GetGlobalRect() const; TileKey const & GetTileKey() const { return m_context->GetTileKey(); } bool operator <(TileInfo const & other) const { return GetTileKey() < other.GetTileKey(); } @@ -50,6 +53,7 @@ private: drape_ptr m_context; vector m_featureInfo; bool m_is3dBuildings; + bool m_trafficEnabled; atomic m_isCanceled; }; diff --git a/drape_frontend/traffic_generator.cpp b/drape_frontend/traffic_generator.cpp index f0780dc53b..8b6fd94a68 100644 --- a/drape_frontend/traffic_generator.cpp +++ b/drape_frontend/traffic_generator.cpp @@ -85,15 +85,15 @@ void GenerateCapTriangles(glsl::vec3 const & pivot, vector const & n } // namespace -TrafficHandle::TrafficHandle(TrafficSegmentID const & segmentId, RoadClass const & roadClass, - m2::RectD const & boundingBox, glsl::vec2 const & texCoord, - size_t verticesCount) +TrafficHandle::TrafficHandle(traffic::TrafficInfo::RoadSegmentId const & segmentId, RoadClass const & roadClass, + m2::RectD const & boundingBox, glsl::vec2 const & texCoord, size_t verticesCount) : OverlayHandle(FeatureID(), dp::Anchor::Center, 0, false) , m_segmentId(segmentId) , m_roadClass(roadClass) , m_boundingBox(boundingBox) , m_needUpdate(false) { + ASSERT_NOT_EQUAL(verticesCount, 0, ()); m_buffer.resize(verticesCount); for (size_t i = 0; i < m_buffer.size(); i++) m_buffer[i] = texCoord; @@ -151,7 +151,7 @@ void TrafficHandle::SetTexCoord(glsl::vec2 const & texCoord) m_needUpdate = true; } -TrafficSegmentID TrafficHandle::GetSegmentId() const +traffic::TrafficInfo::RoadSegmentId const & TrafficHandle::GetSegmentId() const { return m_segmentId; } @@ -181,51 +181,8 @@ void TrafficGenerator::ClearGLDependentResources() m_batchersPool.reset(); } -void TrafficGenerator::AddSegmentsGeometry(TrafficSegmentsGeometry const & geom) -{ - m_segments.insert(geom.begin(), geom.end()); -} - -void TrafficGenerator::ClearCache() -{ - m_colorsCacheValid = false; - m_segmentsCache.clear(); -} - -void TrafficGenerator::ClearCache(MwmSet::MwmId const & mwmId) -{ - auto it = m_segmentsCache.begin(); - while (it != m_segmentsCache.end()) - { - if (it->m_mwmId == mwmId) - it = m_segmentsCache.erase(it); - else - ++it; - } -} - -TrafficSegmentsColoring TrafficGenerator::GetSegmentsToUpdate(TrafficSegmentsColoring const & trafficColoring) const -{ - TrafficSegmentsColoring result; - for (auto const & segment : trafficColoring) - { - if (m_segmentsCache.find(segment.m_id) != m_segmentsCache.end()) - result.push_back(segment); - } - return result; -} - -void TrafficGenerator::FlushGeometry(TrafficBatcherKey const & key, dp::GLState const & state, drape_ptr && buffer) -{ - TrafficRenderData renderData(state); - renderData.m_bucket = move(buffer); - renderData.m_mwmId = key.m_mwmId; - renderData.m_tileKey = key.m_tileKey; - m_flushRenderDataFn(move(renderData)); -} - -void TrafficGenerator::GetTrafficGeom(ref_ptr textures, - TrafficSegmentsColoring const & trafficColoring) +void TrafficGenerator::FlushSegmentsGeometry(TileKey const & tileKey, TrafficSegmentsGeometry const & geom, + ref_ptr textures) { FillColorsCache(textures); @@ -234,72 +191,99 @@ void TrafficGenerator::GetTrafficGeom(ref_ptr textures, state.SetColorTexture(m_colorsCache[static_cast(traffic::SpeedGroup::G0)].GetTexture()); state.SetMaskTexture(textures->GetTrafficArrowTexture()); - int const kZoomLevel = 10; + static vector roadClasses = {RoadClass::Class0, RoadClass::Class1, RoadClass::Class2}; - using TSegIter = TrafficSegmentsGeometry::iterator; - map>> segmentsByTiles; - for (auto const & segment : trafficColoring) + for (auto geomIt = geom.begin(); geomIt != geom.end(); ++geomIt) { - // Check if a segment hasn't been added. - auto it = m_segments.find(segment.m_id); - if (it == m_segments.end()) - continue; - - // Check if a segment has already generated. - if (m_segmentsCache.find(segment.m_id) != m_segmentsCache.end()) - continue; - - m_segmentsCache.insert(segment.m_id); - TileKey const tileKey = GetTileKeyByPoint(it->second.m_polyline.GetLimitRect().Center(), kZoomLevel); - segmentsByTiles[tileKey].emplace_back(make_pair(it, segment.m_speedGroup)); - } - - for (auto const & s : segmentsByTiles) - { - TileKey const & tileKey = s.first; - - for (auto const & segmentPair : s.second) + auto coloringIt = m_coloring.find(geomIt->first); + if (coloringIt != m_coloring.end()) { - TSegIter it = segmentPair.first; + for (size_t i = 0; i < roadClasses.size(); i++) + m_batchersPool->ReserveBatcher(TrafficBatcherKey(geomIt->first, tileKey, roadClasses[i])); - TrafficBatcherKey bk(it->first.m_mwmId, tileKey, it->second.m_roadClass); + auto & coloring = coloringIt->second; + for (size_t i = 0; i < geomIt->second.size(); i++) + { + traffic::TrafficInfo::RoadSegmentId const & sid = geomIt->second[i].first; + auto segmentColoringIt = coloring.find(sid); + if (segmentColoringIt != coloring.end()) + { + TrafficSegmentGeometry const & g = geomIt->second[i].second; + ref_ptr batcher = m_batchersPool->GetBatcher(TrafficBatcherKey(geomIt->first, tileKey, g.m_roadClass)); - m_batchersPool->ReserveBatcher(bk); - ref_ptr batcher = m_batchersPool->GetBatcher(bk); + ASSERT(m_colorsCacheValid, ()); + dp::TextureManager::ColorRegion const & colorRegion = m_colorsCache[static_cast(segmentColoringIt->second)]; - ASSERT(m_colorsCacheValid, ()); - dp::TextureManager::ColorRegion const & colorRegion = m_colorsCache[static_cast(segmentPair.second)]; - m2::PolylineD const & polyline = it->second.m_polyline; + vector staticGeometry; + vector dynamicGeometry; + GenerateSegment(colorRegion, g.m_polyline, tileKey.GetGlobalRect().Center(), staticGeometry, dynamicGeometry); + ASSERT_EQUAL(staticGeometry.size(), dynamicGeometry.size(), ()); - vector staticGeometry; - vector dynamicGeometry; - GenerateSegment(colorRegion, polyline, tileKey.GetGlobalRect().Center(), staticGeometry, dynamicGeometry); - ASSERT_EQUAL(staticGeometry.size(), dynamicGeometry.size(), ()); + if ((staticGeometry.size() + dynamicGeometry.size()) == 0) + continue; - if ((staticGeometry.size() + dynamicGeometry.size()) == 0) - continue; + glsl::vec2 const uv = glsl::ToVec2(colorRegion.GetTexRect().Center()); + drape_ptr handle = make_unique_dp(sid, g.m_roadClass, g.m_polyline.GetLimitRect(), uv, + staticGeometry.size()); - glsl::vec2 const uv = glsl::ToVec2(colorRegion.GetTexRect().Center()); - drape_ptr handle = make_unique_dp(it->first, it->second.m_roadClass, - polyline.GetLimitRect(), uv, - staticGeometry.size()); + dp::AttributeProvider provider(2 /* stream count */, staticGeometry.size()); + provider.InitStream(0 /* stream index */, GetTrafficStaticBindingInfo(), make_ref(staticGeometry.data())); + provider.InitStream(1 /* stream index */, GetTrafficDynamicBindingInfo(), make_ref(dynamicGeometry.data())); + batcher->InsertTriangleList(state, make_ref(&provider), move(handle)); + } + } - dp::AttributeProvider provider(2 /* stream count */, staticGeometry.size()); - provider.InitStream(0 /* stream index */, GetTrafficStaticBindingInfo(), make_ref(staticGeometry.data())); - provider.InitStream(1 /* stream index */, GetTrafficDynamicBindingInfo(), make_ref(dynamicGeometry.data())); - batcher->InsertTriangleList(state, make_ref(&provider), move(handle)); - } - - for (auto const & segmentPair : s.second) - { - m_batchersPool->ReleaseBatcher(TrafficBatcherKey(segmentPair.first->first.m_mwmId, tileKey, - segmentPair.first->second.m_roadClass)); + for (size_t i = 0; i < roadClasses.size(); i++) + m_batchersPool->ReleaseBatcher(TrafficBatcherKey(geomIt->first, tileKey, roadClasses[i])); } } GLFunctions::glFlush(); } +bool TrafficGenerator::UpdateColoring(TrafficSegmentsColoring const & coloring) +{ + // Check for new mwm's in coloring. + bool hasNew = false; + for (auto it = coloring.begin(); it != coloring.end(); ++it) + { + auto const coloringIt = m_coloring.find(it->first); + if (coloringIt == m_coloring.end()) + { + hasNew = true; + break; + } + } + + // Update coloring. + for (auto it = coloring.begin(); it != coloring.end(); ++it) + m_coloring.erase(it->first); + m_coloring.insert(coloring.begin(), coloring.end()); + + return hasNew; +} + +void TrafficGenerator::ClearCache() +{ + m_colorsCacheValid = false; + m_coloring.clear(); +} + +void TrafficGenerator::ClearCache(MwmSet::MwmId const & mwmId) +{ + m_coloring.erase(mwmId); +} + +void TrafficGenerator::FlushGeometry(TrafficBatcherKey const & key, dp::GLState const & state, + drape_ptr && buffer) +{ + TrafficRenderData renderData(state); + renderData.m_bucket = move(buffer); + renderData.m_mwmId = key.m_mwmId; + renderData.m_tileKey = key.m_tileKey; + m_flushRenderDataFn(move(renderData)); +} + void TrafficGenerator::GenerateSegment(dp::TextureManager::ColorRegion const & colorRegion, m2::PolylineD const & polyline, m2::PointD const & tileCenter, vector & staticGeometry, @@ -359,22 +343,22 @@ void TrafficGenerator::GenerateSegment(dp::TextureManager::ColorRegion const & c } // Generate caps. -// if (firstFilled) -// { -// int const kSegmentsCount = 4; -// vector normals; -// normals.reserve(kAverageCapSize); -// GenerateCapNormals(dp::RoundCap, firstLeftNormal, firstRightNormal, -firstTangent, -// 1.0f, true /* isStart */, normals, kSegmentsCount); -// GenerateCapTriangles(glsl::vec3(firstPoint, kDepth), normals, colorRegion, -// staticGeometry, dynamicGeometry); + if (firstFilled) + { + int const kSegmentsCount = 4; + vector normals; + normals.reserve(kAverageCapSize); + GenerateCapNormals(dp::RoundCap, firstLeftNormal, firstRightNormal, -firstTangent, + 1.0f, true /* isStart */, normals, kSegmentsCount); + GenerateCapTriangles(glsl::vec3(firstPoint, kDepth), normals, colorRegion, + staticGeometry, dynamicGeometry); -// normals.clear(); -// GenerateCapNormals(dp::RoundCap, lastLeftNormal, lastRightNormal, lastTangent, -// 1.0f, false /* isStart */, normals, kSegmentsCount); -// GenerateCapTriangles(glsl::vec3(lastPoint, kDepth), normals, colorRegion, -// staticGeometry, dynamicGeometry); -// } + normals.clear(); + GenerateCapNormals(dp::RoundCap, lastLeftNormal, lastRightNormal, lastTangent, + 1.0f, false /* isStart */, normals, kSegmentsCount); + GenerateCapTriangles(glsl::vec3(lastPoint, kDepth), normals, colorRegion, + staticGeometry, dynamicGeometry); + } } void TrafficGenerator::FillColorsCache(ref_ptr textures) diff --git a/drape_frontend/traffic_generator.hpp b/drape_frontend/traffic_generator.hpp index f6031dab2e..7e9450baa3 100644 --- a/drape_frontend/traffic_generator.hpp +++ b/drape_frontend/traffic_generator.hpp @@ -33,6 +33,10 @@ enum class RoadClass : uint8_t Class2 }; +int constexpr kRoadClass0ZoomLevel = 10; +int constexpr kRoadClass1ZoomLevel = 12; +int constexpr kRoadClass2ZoomLevel = 14; + struct TrafficSegmentID { MwmSet::MwmId m_mwmId; @@ -70,20 +74,11 @@ struct TrafficSegmentGeometry {} }; -using TrafficSegmentsGeometry = map; +using TrafficSegmentsGeometry = map>>; +using TrafficSegmentsColoring = map; -struct TrafficSegmentColoring -{ - TrafficSegmentID m_id; - traffic::SpeedGroup m_speedGroup; - - TrafficSegmentColoring(TrafficSegmentID const & id, traffic::SpeedGroup const & speedGroup) - : m_id(id) - , m_speedGroup(speedGroup) - {} -}; - -using TrafficSegmentsColoring = vector; +class TrafficHandle; struct TrafficRenderData { @@ -92,6 +87,8 @@ struct TrafficRenderData TileKey m_tileKey; MwmSet::MwmId m_mwmId; m2::RectD m_boundingBox; + vector m_handles; + TrafficRenderData(dp::GLState const & state) : m_state(state) {} }; @@ -127,7 +124,7 @@ class TrafficHandle : public dp::OverlayHandle using TBase = dp::OverlayHandle; public: - TrafficHandle(TrafficSegmentID const & segmentId, RoadClass const & roadClass, + TrafficHandle(traffic::TrafficInfo::RoadSegmentId const & segmentId, RoadClass const & roadClass, m2::RectD const & boundingBox, glsl::vec2 const & texCoord, size_t verticesCount); @@ -138,12 +135,12 @@ public: void GetPixelShape(ScreenBase const & screen, bool perspective, Rects & rects) const override; void SetTexCoord(glsl::vec2 const & texCoord); - TrafficSegmentID GetSegmentId() const; + traffic::TrafficInfo::RoadSegmentId const & GetSegmentId() const; RoadClass const & GetRoadClass() const; m2::RectD const & GetBoundingBox() const; private: - TrafficSegmentID m_segmentId; + traffic::TrafficInfo::RoadSegmentId m_segmentId; RoadClass m_roadClass; vector m_buffer; m2::RectD m_boundingBox; @@ -164,12 +161,9 @@ public: void Init(); void ClearGLDependentResources(); - void AddSegmentsGeometry(TrafficSegmentsGeometry const & geom); - - TrafficSegmentsColoring GetSegmentsToUpdate(TrafficSegmentsColoring const & trafficColoring) const; - - void GetTrafficGeom(ref_ptr textures, - TrafficSegmentsColoring const & trafficColoring); + void FlushSegmentsGeometry(TileKey const & tileKey, TrafficSegmentsGeometry const & geom, + ref_ptr textures); + bool UpdateColoring(TrafficSegmentsColoring const & coloring); void ClearCache(); void ClearCache(MwmSet::MwmId const & mwmId); @@ -212,11 +206,14 @@ private: vector & dynamicGeometry); void FillColorsCache(ref_ptr textures); - void FlushGeometry(TrafficBatcherKey const & key, dp::GLState const & state, drape_ptr && buffer); + void FlushGeometry(TrafficBatcherKey const & key, dp::GLState const & state, + drape_ptr && buffer); - TrafficSegmentsGeometry m_segments; + TrafficSegmentsColoring m_coloring; - set m_segmentsCache; + //map m_segments; + + //set m_segmentsCache; array(traffic::SpeedGroup::Count)> m_colorsCache; bool m_colorsCacheValid = false; bool m_colorsCacheRefreshed = false; diff --git a/drape_frontend/traffic_renderer.cpp b/drape_frontend/traffic_renderer.cpp index 31d13d56d0..ca55154ba0 100644 --- a/drape_frontend/traffic_renderer.cpp +++ b/drape_frontend/traffic_renderer.cpp @@ -19,14 +19,9 @@ namespace df namespace { -int const kMinVisibleZoomLevel = 10; - int const kMinVisibleArrowZoomLevel = 16; int const kRoadClass2MinVisibleArrowZoomLevel = 18; -int const kRoadClass1ZoomLevel = 12; -int const kRoadClass2ZoomLevel = 14; - float const kTrafficArrowAspect = 24.0f / 8.0f; float const kLeftWidthInPixel[] = @@ -96,6 +91,14 @@ float CalculateHalfWidth(ScreenBase const & screen, RoadClass const & roadClass, void TrafficRenderer::AddRenderData(ref_ptr mng, TrafficRenderData && renderData) { + // Remove obsolete render data. + TileKey const tileKey(renderData.m_tileKey); + m_renderData.erase(remove_if(m_renderData.begin(), m_renderData.end(), [&tileKey](TrafficRenderData const & rd) + { + return tileKey == rd.m_tileKey && rd.m_tileKey.m_generation < tileKey.m_generation; + }), m_renderData.end()); + + // Add new render data. m_renderData.emplace_back(move(renderData)); TrafficRenderData & rd = m_renderData.back(); @@ -103,25 +106,56 @@ void TrafficRenderer::AddRenderData(ref_ptr mng, TrafficR program->Bind(); rd.m_bucket->GetBuffer()->Build(program); + rd.m_handles.reserve(rd.m_bucket->GetOverlayHandlesCount()); for (size_t j = 0; j < rd.m_bucket->GetOverlayHandlesCount(); j++) { TrafficHandle * handle = static_cast(rd.m_bucket->GetOverlayHandle(j).get()); - m_handles.insert(make_pair(handle->GetSegmentId(), handle)); + rd.m_handles.emplace_back(handle); rd.m_boundingBox.Add(handle->GetBoundingBox()); } } +void TrafficRenderer::OnUpdateViewport(CoverageResult const & coverage, int currentZoomLevel, + buffer_vector const & tilesToDelete) +{ + m_renderData.erase(remove_if(m_renderData.begin(), m_renderData.end(), + [&coverage, ¤tZoomLevel, &tilesToDelete](TrafficRenderData const & rd) + { + return rd.m_tileKey.m_zoomLevel == currentZoomLevel && + (rd.m_tileKey.m_x < coverage.m_minTileX || rd.m_tileKey.m_x >= coverage.m_maxTileX || + rd.m_tileKey.m_y < coverage.m_minTileY || rd.m_tileKey.m_y >= coverage.m_maxTileY || + find(tilesToDelete.begin(), tilesToDelete.end(), rd.m_tileKey) != tilesToDelete.end()); + }), m_renderData.end()); +} + +void TrafficRenderer::OnGeometryReady(int currentZoomLevel) +{ + m_renderData.erase(remove_if(m_renderData.begin(), m_renderData.end(), + [¤tZoomLevel](TrafficRenderData const & rd) + { + return rd.m_tileKey.m_zoomLevel != currentZoomLevel; + }), m_renderData.end()); +} + void TrafficRenderer::UpdateTraffic(TrafficSegmentsColoring const & trafficColoring) { - for (auto const & segment : trafficColoring) + for (TrafficRenderData & renderData : m_renderData) { - auto it = m_texCoords.find(static_cast(segment.m_speedGroup)); - if (it == m_texCoords.end()) + auto coloringIt = trafficColoring.find(renderData.m_mwmId); + if (coloringIt == trafficColoring.end()) continue; - auto handleIt = m_handles.find(segment.m_id); - if (handleIt != m_handles.end()) - handleIt->second->SetTexCoord(it->second); + for (size_t i = 0; i < renderData.m_handles.size(); i++) + { + auto it = coloringIt->second.find(renderData.m_handles[i]->GetSegmentId()); + if (it != coloringIt->second.end()) + { + auto texCoordIt = m_texCoords.find(static_cast(it->second)); + if (texCoordIt == m_texCoords.end()) + continue; + renderData.m_handles[i]->SetTexCoord(texCoordIt->second); + } + } } } @@ -129,7 +163,7 @@ void TrafficRenderer::RenderTraffic(ScreenBase const & screen, int zoomLevel, ref_ptr mng, dp::UniformValuesStorage const & commonUniforms) { - if (m_renderData.empty() || zoomLevel < kMinVisibleZoomLevel) + if (m_renderData.empty() || zoomLevel < kRoadClass0ZoomLevel) return; m2::RectD const clipRect = screen.ClipRect(); @@ -151,7 +185,7 @@ void TrafficRenderer::RenderTraffic(ScreenBase const & screen, int zoomLevel, TrafficHandle * handle = static_cast(renderData.m_bucket->GetOverlayHandle(0).get()); ASSERT(handle != nullptr, ()); - int visibleZoomLevel = kMinVisibleZoomLevel; + int visibleZoomLevel = kRoadClass0ZoomLevel; if (handle->GetRoadClass() == RoadClass::Class1) { visibleZoomLevel = kRoadClass1ZoomLevel; @@ -197,7 +231,6 @@ void TrafficRenderer::SetTexCoords(TrafficTexCoords && texCoords) void TrafficRenderer::ClearGLDependentResources() { m_renderData.clear(); - m_handles.clear(); m_texCoords.clear(); } diff --git a/drape_frontend/traffic_renderer.hpp b/drape_frontend/traffic_renderer.hpp index d7d38af220..4544d1a9ce 100644 --- a/drape_frontend/traffic_renderer.hpp +++ b/drape_frontend/traffic_renderer.hpp @@ -1,6 +1,7 @@ #pragma once #include "drape_frontend/traffic_generator.hpp" +#include "drape_frontend/tile_utils.hpp" #include "drape/gpu_program_manager.hpp" #include "drape/pointers.hpp" @@ -9,7 +10,6 @@ #include "geometry/screenbase.hpp" #include "geometry/spline.hpp" -#include "std/map.hpp" #include "std/vector.hpp" namespace df @@ -34,10 +34,13 @@ public: void ClearGLDependentResources(); void Clear(MwmSet::MwmId const & mwmId); + void OnUpdateViewport(CoverageResult const & coverage, int currentZoomLevel, + buffer_vector const & tilesToDelete); + void OnGeometryReady(int currentZoomLevel); + private: vector m_renderData; TrafficTexCoords m_texCoords; - map m_handles; }; } // namespace df diff --git a/geometry/polyline2d.hpp b/geometry/polyline2d.hpp index 86dfe69972..abe2459ebe 100644 --- a/geometry/polyline2d.hpp +++ b/geometry/polyline2d.hpp @@ -115,7 +115,7 @@ public: return m_points.back(); } - Polyline ExtractSegment(size_t segmentIndex, bool reversed) + Polyline ExtractSegment(size_t segmentIndex, bool reversed) const { if (segmentIndex + 1 >= m_points.size()) return Polyline(); diff --git a/map/framework.cpp b/map/framework.cpp index bb334c421b..5b1f751771 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -121,6 +121,7 @@ char const kMapStyleKey[] = "MapStyleKeyV1"; char const kAllow3dKey[] = "Allow3d"; char const kAllow3dBuildingsKey[] = "Buildings3d"; char const kAllowAutoZoom[] = "AutoZoom"; +char const kTrafficEnabledKey[] = "TrafficEnabled"; double const kDistEqualQueryMeters = 100.0; @@ -343,8 +344,7 @@ Framework::Framework() , m_isRenderingEnabled(true) , m_trackingReporter(platform::CreateSocket(), TRACKING_REALTIME_HOST, TRACKING_REALTIME_PORT, tracking::Reporter::kPushDelayMs) - , m_trafficManager(m_model.GetIndex(), bind(&Framework::GetMwmsByRect, this, _1), - kMaxTrafficCacheSizeBytes) + , m_trafficManager(bind(&Framework::GetMwmsByRect, this, _1), kMaxTrafficCacheSizeBytes) , m_displacementModeManager([this](bool show) { int const mode = show ? dp::displacement::kHotelMode : dp::displacement::kDefaultMode; CallDrapeFunction(bind(&df::DrapeEngine::SetDisplacementMode, _1, mode)); @@ -1605,6 +1605,8 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, Load3dMode(allow3d, allow3dBuildings); bool const isAutozoomEnabled = LoadAutoZoom(); + bool const trafficEnabled = LoadTrafficEnabled(); + m_trafficManager.SetEnabled(trafficEnabled); df::DrapeEngine::Params p(contextFactory, make_ref(&m_stringsBundle), @@ -1612,7 +1614,7 @@ void Framework::CreateDrapeEngine(ref_ptr contextFactory, df::MapDataProvider(idReadFn, featureReadFn, isCountryLoadedByNameFn, updateCurrentCountryFn), params.m_visualScale, move(params.m_widgetsInitInfo), make_pair(params.m_initialMyPositionState, params.m_hasMyPositionState), - allow3dBuildings, params.m_isChoosePositionMode, + allow3dBuildings, trafficEnabled, params.m_isChoosePositionMode, params.m_isChoosePositionMode, GetSelectedFeatureTriangles(), params.m_isFirstLaunch, m_routingSession.IsActive() && m_routingSession.IsFollowing(), isAutozoomEnabled); @@ -2646,6 +2648,18 @@ void Framework::Load3dMode(bool & allow3d, bool & allow3dBuildings) allow3dBuildings = true; } +bool Framework::LoadTrafficEnabled() +{ + bool enabled = true; //TODO(@rokuz): temporary. It has to be false by default. + settings::Get(kTrafficEnabledKey, enabled); + return enabled; +} + +void Framework::SaveTrafficEnabled(bool trafficEnabled) +{ + settings::Set(kTrafficEnabledKey, trafficEnabled); +} + bool Framework::LoadAutoZoom() { bool allowAutoZoom = true; diff --git a/map/framework.hpp b/map/framework.hpp index 338eacc328..4f5f689e41 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -773,6 +773,9 @@ public: void AllowAutoZoom(bool allowAutoZoom); void SaveAutoZoom(bool allowAutoZoom); + bool LoadTrafficEnabled(); + void SaveTrafficEnabled(bool trafficEnabled); + /// \returns true if altitude information along |m_route| is available and /// false otherwise. bool HasRouteAltitude() const; diff --git a/map/traffic_manager.cpp b/map/traffic_manager.cpp index 9cd76190d7..bd3ff9fdd9 100644 --- a/map/traffic_manager.cpp +++ b/map/traffic_manager.cpp @@ -11,15 +11,10 @@ namespace { auto const kUpdateInterval = minutes(1); - -int const kMinTrafficZoom = 10; - } // namespace -TrafficManager::TrafficManager(Index const & index, GetMwmsByRectFn const & getMwmsByRectFn, - size_t maxCacheSizeBytes) - : m_isEnabled(true) // TODO: true is temporary - , m_index(index) +TrafficManager::TrafficManager(GetMwmsByRectFn const & getMwmsByRectFn, size_t maxCacheSizeBytes) + : m_isEnabled(false) , m_getMwmsByRectFn(getMwmsByRectFn) , m_maxCacheSizeBytes(maxCacheSizeBytes) , m_currentCacheSizeBytes(0) @@ -42,6 +37,8 @@ TrafficManager::~TrafficManager() void TrafficManager::SetEnabled(bool enabled) { m_isEnabled = enabled; + if (m_drapeEngine != nullptr) + m_drapeEngine->EnableTraffic(enabled); } void TrafficManager::SetDrapeEngine(ref_ptr engine) @@ -64,7 +61,7 @@ void TrafficManager::UpdateViewport(ScreenBase const & screen) if (!m_isEnabled) return; - if (df::GetZoomLevel(screen.GetScale()) < kMinTrafficZoom) + if (df::GetZoomLevel(screen.GetScale()) < df::kRoadClass0ZoomLevel) return; // Request traffic. @@ -98,64 +95,6 @@ void TrafficManager::UpdateMyPosition(MyPosition const & myPosition) // 3. Do all routing stuff. } -void TrafficManager::CalculateSegmentsGeometry(traffic::TrafficInfo const & trafficInfo, - df::TrafficSegmentsGeometry & output) const -{ - size_t const coloringSize = trafficInfo.GetColoring().size(); - - vector features; - features.reserve(coloringSize); - for (auto const & c : trafficInfo.GetColoring()) - features.emplace_back(trafficInfo.GetMwmId(), c.first.m_fid); - - int constexpr kScale = scales::GetUpperScale(); - unordered_map> polylines; - auto featureReader = [&polylines](FeatureType & ft) - { - uint32_t const fid = ft.GetID().m_index; - if (polylines.find(fid) != polylines.end()) - return; - - if (routing::IsRoad(feature::TypesHolder(ft))) - { - auto const highwayClass = ftypes::GetHighwayClass(ft); - df::RoadClass roadClass = df::RoadClass::Class2; - if (highwayClass == ftypes::HighwayClass::Trunk || highwayClass == ftypes::HighwayClass::Primary) - roadClass = df::RoadClass::Class0; - else if (highwayClass == ftypes::HighwayClass::Secondary || highwayClass == ftypes::HighwayClass::Tertiary) - roadClass = df::RoadClass::Class1; - - m2::PolylineD polyline; - ft.ForEachPoint([&polyline](m2::PointD const & pt) { polyline.Add(pt); }, kScale); - if (polyline.GetSize() > 1) - polylines[fid] = make_pair(polyline, roadClass); - } - }; - m_index.ReadFeatures(featureReader, features); - - for (auto const & c : trafficInfo.GetColoring()) - { - auto it = polylines.find(c.first.m_fid); - if (it == polylines.end()) - continue; - bool const isReversed = (c.first.m_dir == traffic::TrafficInfo::RoadSegmentId::kReverseDirection); - m2::PolylineD polyline = it->second.first.ExtractSegment(c.first.m_idx, isReversed); - if (polyline.GetSize() > 1) - output.insert(make_pair(df::TrafficSegmentID(trafficInfo.GetMwmId(), c.first), - df::TrafficSegmentGeometry(move(polyline), it->second.second))); - } -} - -void TrafficManager::CalculateSegmentsColoring(traffic::TrafficInfo const & trafficInfo, - df::TrafficSegmentsColoring & output) const -{ - for (auto const & c : trafficInfo.GetColoring()) - { - df::TrafficSegmentID const sid (trafficInfo.GetMwmId(), c.first); - output.emplace_back(sid, c.second); - } -} - void TrafficManager::ThreadRoutine() { vector mwms; @@ -235,25 +174,17 @@ void TrafficManager::OnTrafficDataResponse(traffic::TrafficInfo const & info) if (it == m_mwmInfos.end()) return; - // Cache geometry for rendering if it's necessary. - if (!it->second.m_isLoaded) - { - df::TrafficSegmentsGeometry geometry; - CalculateSegmentsGeometry(info, geometry); - it->second.m_isLoaded = true; - m_drapeEngine->CacheTrafficSegmentsGeometry(geometry); - } + // Update cache. + size_t constexpr kElementSize = sizeof(traffic::TrafficInfo::RoadSegmentId) + sizeof(traffic::SpeedGroup); + size_t const dataSize = info.GetColoring().size() * kElementSize; + it->second.m_isLoaded = true; + m_currentCacheSizeBytes += (dataSize - it->second.m_dataSize); + it->second.m_dataSize = dataSize; + CheckCacheSize(); // Update traffic colors. df::TrafficSegmentsColoring coloring; - CalculateSegmentsColoring(info, coloring); - - size_t dataSize = coloring.size() * sizeof(df::TrafficSegmentColoring); - it->second.m_dataSize = dataSize; - m_currentCacheSizeBytes += dataSize; - - CheckCacheSize(); - + coloring[info.GetMwmId()] = info.GetColoring(); m_drapeEngine->UpdateTraffic(coloring); } diff --git a/map/traffic_manager.hpp b/map/traffic_manager.hpp index 9a209fe8a0..ae7838251c 100644 --- a/map/traffic_manager.hpp +++ b/map/traffic_manager.hpp @@ -42,8 +42,7 @@ public: using GetMwmsByRectFn = function(m2::RectD const &)>; - TrafficManager(Index const & index, GetMwmsByRectFn const & getMwmsByRectFn, - size_t maxCacheSizeBytes); + TrafficManager(GetMwmsByRectFn const & getMwmsByRectFn, size_t maxCacheSizeBytes); ~TrafficManager(); void SetEnabled(bool enabled); @@ -56,11 +55,6 @@ public: void SetDrapeEngine(ref_ptr engine); private: - void CalculateSegmentsGeometry(traffic::TrafficInfo const & trafficInfo, - df::TrafficSegmentsGeometry & output) const; - void CalculateSegmentsColoring(traffic::TrafficInfo const & trafficInfo, - df::TrafficSegmentsColoring & output) const; - void ThreadRoutine(); bool WaitForRequest(vector & mwms); void RequestTrafficData(); @@ -70,7 +64,6 @@ private: bool m_isEnabled; - Index const & m_index; GetMwmsByRectFn m_getMwmsByRectFn; ref_ptr m_drapeEngine;