Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaria Volvenkova <d.volvenkova@corp.mail.ru>2017-06-05 18:38:19 +0300
committerGitHub <noreply@github.com>2017-06-05 18:38:19 +0300
commit3ea5960a80e0a9bf167294a1147505d934616b25 (patch)
tree0299b482a463c67c7f37f9337a87a99826d89df8
parent510d21af957dc044804b2612c5dbdeb387f57b3b (diff)
parent03b3412d02a4b7c6e342f02b3e58d419b52dbe3a (diff)
Merge pull request #6190 from rokuz/refactored-route-rendererbeta-847
Multiple route renderer
-rw-r--r--android/jni/com/mapswithme/maps/Framework.cpp6
-rw-r--r--drape/drape_global.hpp4
-rw-r--r--drape_frontend/backend_renderer.cpp36
-rw-r--r--drape_frontend/drape_engine.cpp27
-rw-r--r--drape_frontend/drape_engine.hpp18
-rwxr-xr-xdrape_frontend/frontend_renderer.cpp98
-rwxr-xr-xdrape_frontend/frontend_renderer.hpp2
-rw-r--r--drape_frontend/message.hpp6
-rw-r--r--drape_frontend/message_subclasses.hpp119
-rw-r--r--drape_frontend/route_builder.cpp51
-rw-r--r--drape_frontend/route_builder.hpp26
-rw-r--r--drape_frontend/route_renderer.cpp453
-rw-r--r--drape_frontend/route_renderer.hpp58
-rw-r--r--drape_frontend/route_shape.cpp143
-rw-r--r--drape_frontend/route_shape.hpp68
-rw-r--r--iphone/Maps/Core/Routing/MWMRouter.mm4
-rw-r--r--map/place_page_info.cpp6
-rw-r--r--map/place_page_info.hpp1
-rw-r--r--map/routing_manager.cpp122
-rw-r--r--map/routing_manager.hpp21
20 files changed, 614 insertions, 655 deletions
diff --git a/android/jni/com/mapswithme/maps/Framework.cpp b/android/jni/com/mapswithme/maps/Framework.cpp
index f91f3c5e5e..7a9ae5d835 100644
--- a/android/jni/com/mapswithme/maps/Framework.cpp
+++ b/android/jni/com/mapswithme/maps/Framework.cpp
@@ -1146,14 +1146,16 @@ Java_com_mapswithme_maps_Framework_nativeGetBestRouter(JNIEnv * env, jclass, jdo
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_Framework_nativeSetRouteStartPoint(JNIEnv * env, jclass, jdouble lat, jdouble lon, jboolean valid)
{
- frm()->GetRoutingManager().SetRouteStartPoint(m2::PointD(MercatorBounds::FromLatLon(lat, lon)),
+ frm()->GetRoutingManager().SetRouteStartPoint(frm()->GetBookmarkManager(),
+ m2::PointD(MercatorBounds::FromLatLon(lat, lon)),
static_cast<bool>(valid));
}
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_Framework_nativeSetRouteEndPoint(JNIEnv * env, jclass, jdouble lat, jdouble lon, jboolean valid)
{
- frm()->GetRoutingManager().SetRouteFinishPoint(m2::PointD(MercatorBounds::FromLatLon(lat, lon)),
+ frm()->GetRoutingManager().SetRouteFinishPoint(frm()->GetBookmarkManager(),
+ m2::PointD(MercatorBounds::FromLatLon(lat, lon)),
static_cast<bool>(valid));
}
diff --git a/drape/drape_global.hpp b/drape/drape_global.hpp
index 8511bd8cf4..628714e2e2 100644
--- a/drape/drape_global.hpp
+++ b/drape/drape_global.hpp
@@ -4,6 +4,8 @@
#include "base/assert.hpp"
+#include <cstdint>
+
namespace dp
{
enum ApiVersion
@@ -60,6 +62,8 @@ enum LineJoin
RoundJoin = 1,
};
+using DrapeID = uint64_t;
+
struct FontDecl
{
FontDecl() = default;
diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp
index d42f4fb08e..5f4bc53bb2 100644
--- a/drape_frontend/backend_renderer.cpp
+++ b/drape_frontend/backend_renderer.cpp
@@ -45,17 +45,12 @@ BackendRenderer::BackendRenderer(Params && params)
m_routeBuilder = make_unique_dp<RouteBuilder>([this](drape_ptr<RouteData> && routeData)
{
m_commutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<FlushRouteMessage>(move(routeData)),
- MessagePriority::Normal);
- }, [this](drape_ptr<RouteSignData> && routeSignData)
- {
- m_commutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<FlushRouteSignMessage>(move(routeSignData)),
+ make_unique_dp<FlushRouteMessage>(std::move(routeData)),
MessagePriority::Normal);
}, [this](drape_ptr<RouteArrowsData> && routeArrowsData)
{
m_commutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<FlushRouteArrowsMessage>(move(routeArrowsData)),
+ make_unique_dp<FlushRouteArrowsMessage>(std::move(routeArrowsData)),
MessagePriority::Normal);
});
@@ -271,36 +266,31 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message)
break;
}
- case Message::AddRoute:
- {
- ref_ptr<AddRouteMessage> msg = message;
- m_routeBuilder->Build(msg->GetRoutePolyline(), msg->GetTurns(), msg->GetColor(),
- msg->GetTraffic(), msg->GetPattern(), m_texMng, msg->GetRecacheId());
- break;
- }
-
- case Message::CacheRouteSign:
+ case Message::AddRouteSegment:
{
- ref_ptr<CacheRouteSignMessage> msg = message;
- m_routeBuilder->BuildSign(msg->GetPosition(), msg->IsStart(), msg->IsValid(), m_texMng, msg->GetRecacheId());
+ ref_ptr<AddRouteSegmentMessage> msg = message;
+ m_routeBuilder->Build(msg->GetSegmentId(), msg->GetRouteSegment(), m_texMng,
+ msg->GetRecacheId());
break;
}
case Message::CacheRouteArrows:
{
ref_ptr<CacheRouteArrowsMessage> msg = message;
- m_routeBuilder->BuildArrows(msg->GetRouteIndex(), msg->GetBorders(), m_texMng, msg->GetRecacheId());
+ m_routeBuilder->BuildArrows(msg->GetSegmentId(), msg->GetBorders(), m_texMng,
+ msg->GetRecacheId());
break;
}
- case Message::RemoveRoute:
+ case Message::RemoveRouteSegment:
{
- ref_ptr<RemoveRouteMessage> msg = message;
+ ref_ptr<RemoveRouteSegmentMessage> msg = message;
m_routeBuilder->ClearRouteCache();
// We have to resend the message to FR, because it guaranties that
- // RemoveRouteMessage will be processed after FlushRouteMessage.
+ // RemoveRouteSegment will be processed after FlushRouteMessage.
m_commutator->PostMessage(ThreadsCommutator::RenderThread,
- make_unique_dp<RemoveRouteMessage>(msg->NeedDeactivateFollowing()),
+ make_unique_dp<RemoveRouteSegmentMessage>(
+ msg->GetSegmentId(), msg->NeedDeactivateFollowing()),
MessagePriority::Normal);
break;
}
diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp
index 3a0e9069a5..14d2eb5b5b 100644
--- a/drape_frontend/drape_engine.cpp
+++ b/drape_frontend/drape_engine.cpp
@@ -257,6 +257,13 @@ void DrapeEngine::RecacheMapShapes()
MessagePriority::Normal);
}
+dp::DrapeID DrapeEngine::GenerateDrapeID()
+{
+ std::lock_guard<std::mutex> lock(m_drapeIdGeneratorMutex);
+ ++m_drapeIdGenerator;
+ return m_drapeIdGenerator;
+}
+
void DrapeEngine::RecacheGui(bool needResetOldGui)
{
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
@@ -414,20 +421,19 @@ bool DrapeEngine::GetMyPosition(m2::PointD & myPosition)
return hasPosition;
}
-void DrapeEngine::AddRoute(m2::PolylineD const & routePolyline, std::vector<double> const & turns,
- df::ColorConstant color, std::vector<traffic::SpeedGroup> const & traffic,
- df::RoutePattern pattern)
+dp::DrapeID DrapeEngine::AddRouteSegment(drape_ptr<RouteSegment> && segment)
{
+ dp::DrapeID const id = GenerateDrapeID();
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
- make_unique_dp<AddRouteMessage>(routePolyline, turns,
- color, traffic, pattern),
+ make_unique_dp<AddRouteSegmentMessage>(id, std::move(segment)),
MessagePriority::Normal);
+ return id;
}
-void DrapeEngine::RemoveRoute(bool deactivateFollowing)
+void DrapeEngine::RemoveRouteSegment(dp::DrapeID segmentId, bool deactivateFollowing)
{
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
- make_unique_dp<RemoveRouteMessage>(deactivateFollowing),
+ make_unique_dp<RemoveRouteSegmentMessage>(segmentId, deactivateFollowing),
MessagePriority::Normal);
}
@@ -438,13 +444,6 @@ void DrapeEngine::DeactivateRouteFollowing()
MessagePriority::Normal);
}
-void DrapeEngine::SetRoutePoint(m2::PointD const & position, bool isStart, bool isValid)
-{
- m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
- make_unique_dp<CacheRouteSignMessage>(position, isStart, isValid),
- MessagePriority::Normal);
-}
-
void DrapeEngine::SetWidgetLayout(gui::TWidgetsLayoutInfo && info)
{
m_widgetsLayout = std::move(info);
diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp
index b277ac5bfe..10c0dd8cb6 100644
--- a/drape_frontend/drape_engine.hpp
+++ b/drape_frontend/drape_engine.hpp
@@ -12,6 +12,7 @@
#include "drape_frontend/selection_shape.hpp"
#include "drape_frontend/threads_commutator.hpp"
+#include "drape/drape_global.hpp"
#include "drape/pointers.hpp"
#include "drape/texture_manager.hpp"
#include "drape/viewport.hpp"
@@ -27,6 +28,7 @@
#include "base/strings_bundle.hpp"
#include <functional>
+#include <mutex>
#include <vector>
namespace dp
@@ -139,7 +141,8 @@ public:
void UpdateMapStyle();
void SetCompassInfo(location::CompassInfo const & info);
- void SetGpsInfo(location::GpsInfo const & info, bool isNavigable, location::RouteMatchingInfo const & routeInfo);
+ void SetGpsInfo(location::GpsInfo const & info, bool isNavigable,
+ location::RouteMatchingInfo const & routeInfo);
void SwitchMyPositionNextMode();
void LoseLocation();
void StopLocationFollow();
@@ -156,13 +159,11 @@ public:
bool GetMyPosition(m2::PointD & myPosition);
SelectionShape::ESelectedObject GetSelectedObject();
- void AddRoute(m2::PolylineD const & routePolyline, std::vector<double> const & turns,
- df::ColorConstant color, std::vector<traffic::SpeedGroup> const & traffic,
- df::RoutePattern pattern = df::RoutePattern());
- void RemoveRoute(bool deactivateFollowing);
+ dp::DrapeID AddRouteSegment(drape_ptr<RouteSegment> && segment);
+ void RemoveRouteSegment(dp::DrapeID segmentId, bool deactivateFollowing);
+
void FollowRoute(int preferredZoomLevel, int preferredZoomLevel3d, bool enableAutoZoom);
void DeactivateRouteFollowing();
- void SetRoutePoint(m2::PointD const & position, bool isStart, bool isValid);
void SetWidgetLayout(gui::TWidgetsLayoutInfo && info);
@@ -221,6 +222,8 @@ private:
void RecacheGui(bool needResetOldGui);
void RecacheMapShapes();
+ dp::DrapeID GenerateDrapeID();
+
drape_ptr<FrontendRenderer> m_frontend;
drape_ptr<BackendRenderer> m_backend;
drape_ptr<ThreadsCommutator> m_threadCommutator;
@@ -240,6 +243,9 @@ private:
bool m_choosePositionMode = false;
bool m_kineticScrollEnabled = true;
+ std::mutex m_drapeIdGeneratorMutex;
+ dp::DrapeID m_drapeIdGenerator = 0;
+
friend class DrapeApi;
};
diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp
index 6611c5e6d1..8d93e0bbe7 100755
--- a/drape_frontend/frontend_renderer.cpp
+++ b/drape_frontend/frontend_renderer.cpp
@@ -464,69 +464,54 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
{
ref_ptr<FlushRouteMessage> msg = message;
drape_ptr<RouteData> routeData = msg->AcceptRouteData();
-
- if (routeData->m_recacheId > 0 && routeData->m_recacheId < m_lastRecacheRouteId)
+ if (!CheckRouteRecaching(make_ref(routeData)))
break;
- m2::PointD const finishPoint = routeData->m_sourcePolyline.Back();
- m_routeRenderer->SetRouteData(std::move(routeData), make_ref(m_gpuProgramManager));
+ m_routeRenderer->AddRouteData(std::move(routeData), make_ref(m_gpuProgramManager));
+
// Here we have to recache route arrows.
m_routeRenderer->UpdateRoute(m_userEventStream.GetCurrentScreen(),
std::bind(&FrontendRenderer::OnCacheRouteArrows, this, _1, _2));
- if (!m_routeRenderer->GetFinishPoint())
- {
- m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
- make_unique_dp<CacheRouteSignMessage>(finishPoint, false /* isStart */,
- true /* isValid */),
- MessagePriority::High);
- }
-
if (m_pendingFollowRoute != nullptr)
{
- FollowRoute(m_pendingFollowRoute->m_preferredZoomLevel, m_pendingFollowRoute->m_preferredZoomLevelIn3d,
+ FollowRoute(m_pendingFollowRoute->m_preferredZoomLevel,
+ m_pendingFollowRoute->m_preferredZoomLevelIn3d,
m_pendingFollowRoute->m_enableAutoZoom);
m_pendingFollowRoute.reset();
}
break;
}
- case Message::FlushRouteSign:
- {
- ref_ptr<FlushRouteSignMessage> msg = message;
- drape_ptr<RouteSignData> routeSignData = msg->AcceptRouteSignData();
-
- if (routeSignData->m_recacheId > 0 && routeSignData->m_recacheId < m_lastRecacheRouteId)
- break;
-
- m_routeRenderer->SetRouteSign(std::move(routeSignData), make_ref(m_gpuProgramManager));
- break;
- }
-
case Message::FlushRouteArrows:
{
ref_ptr<FlushRouteArrowsMessage> msg = message;
drape_ptr<RouteArrowsData> routeArrowsData = msg->AcceptRouteArrowsData();
-
- if (routeArrowsData->m_recacheId > 0 && routeArrowsData->m_recacheId < m_lastRecacheRouteId)
- break;
-
- m_routeRenderer->SetRouteArrows(std::move(routeArrowsData), make_ref(m_gpuProgramManager));
+ if (CheckRouteRecaching(make_ref(routeArrowsData)))
+ {
+ m_routeRenderer->AddRouteArrowsData(std::move(routeArrowsData),
+ make_ref(m_gpuProgramManager));
+ }
break;
}
- case Message::RemoveRoute:
+ case Message::RemoveRouteSegment:
{
- ref_ptr<RemoveRouteMessage> msg = message;
- m_routeRenderer->Clear();
- ++m_lastRecacheRouteId;
+ ref_ptr<RemoveRouteSegmentMessage> msg = message;
if (msg->NeedDeactivateFollowing())
{
+ m_routeRenderer->SetFollowingEnabled(false);
+ m_routeRenderer->Clear();
+ ++m_lastRecacheRouteId;
m_myPositionController->DeactivateRouting();
m_overlayTree->SetFollowingMode(false);
if (m_enablePerspectiveInNavigation)
DisablePerspective();
}
+ else
+ {
+ m_routeRenderer->RemoveRouteData(msg->GetSegmentId());
+ }
break;
}
@@ -536,7 +521,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
// After night style switching or drape engine reinitialization FrontendRenderer can
// receive FollowRoute message before FlushRoute message, so we need to postpone its processing.
- if (m_routeRenderer->GetRouteData() == nullptr)
+ if (m_routeRenderer->GetRouteData().empty())
{
m_pendingFollowRoute = my::make_unique<FollowRouteData>(msg->GetPreferredZoomLevel(),
msg->GetPreferredZoomLevelIn3d(),
@@ -817,35 +802,15 @@ void FrontendRenderer::UpdateGLResources()
{
++m_lastRecacheRouteId;
- // Invalidate route.
- if (m_routeRenderer->GetStartPoint())
- {
- m2::PointD const & position = m_routeRenderer->GetStartPoint()->m_position;
- m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
- make_unique_dp<CacheRouteSignMessage>(position, true /* isStart */,
- true /* isValid */, m_lastRecacheRouteId),
- MessagePriority::High);
- }
-
- if (m_routeRenderer->GetFinishPoint())
- {
- m2::PointD const & position = m_routeRenderer->GetFinishPoint()->m_position;
- m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
- make_unique_dp<CacheRouteSignMessage>(position, false /* isStart */,
- true /* isValid */, m_lastRecacheRouteId),
- MessagePriority::High);
- }
-
- auto const & routeData = m_routeRenderer->GetRouteData();
- if (routeData != nullptr)
+ for (auto const & routeData : m_routeRenderer->GetRouteData())
{
- auto recacheRouteMsg = make_unique_dp<AddRouteMessage>(routeData->m_sourcePolyline, routeData->m_sourceTurns,
- routeData->m_color, routeData->m_traffic,
- routeData->m_pattern, m_lastRecacheRouteId);
- m_routeRenderer->ClearGLDependentResources();
- m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, std::move(recacheRouteMsg),
+ auto msg = make_unique_dp<AddRouteSegmentMessage>(routeData->m_segmentId,
+ std::move(routeData->m_segment),
+ m_lastRecacheRouteId);
+ m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, std::move(msg),
MessagePriority::Normal);
}
+ m_routeRenderer->ClearRouteData();
m_trafficRenderer->ClearGLDependentResources();
@@ -872,6 +837,16 @@ void FrontendRenderer::FollowRoute(int preferredZoomLevel, int preferredZoomLeve
AddUserEvent(make_unique_dp<SetAutoPerspectiveEvent>(true /* isAutoPerspective */));
m_overlayTree->SetFollowingMode(true);
+
+ m_routeRenderer->SetFollowingEnabled(true);
+}
+
+bool FrontendRenderer::CheckRouteRecaching(ref_ptr<BaseRouteData> routeData)
+{
+ if (routeData->m_recacheId < 0)
+ return true;
+
+ return routeData->m_recacheId >= m_lastRecacheRouteId;
}
void FrontendRenderer::InvalidateRect(m2::RectD const & gRect)
@@ -1187,7 +1162,6 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
{
StencilWriterGuard guard(make_ref(m_postprocessRenderer));
RenderUserMarksLayer(modelView);
- m_routeRenderer->RenderRouteSigns(modelView, make_ref(m_gpuProgramManager), m_generalUniforms);
}
m_myPositionController->Render(modelView, m_currentZoomLevel, make_ref(m_gpuProgramManager),
diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp
index 1bf7750189..0ab7728a5f 100755
--- a/drape_frontend/frontend_renderer.hpp
+++ b/drape_frontend/frontend_renderer.hpp
@@ -209,6 +209,8 @@ private:
void RemoveRenderGroupsLater(TRenderGroupRemovePredicate const & predicate);
void FollowRoute(int preferredZoomLevel, int preferredZoomLevelIn3d, bool enableAutoZoom);
+ bool CheckRouteRecaching(ref_ptr<BaseRouteData> routeData);
+
void InvalidateRect(m2::RectD const & gRect);
bool CheckTileGenerations(TileKey const & tileKey);
void UpdateCanBeDeletedStatus();
diff --git a/drape_frontend/message.hpp b/drape_frontend/message.hpp
index 8497ac901f..a18c6fa4ac 100644
--- a/drape_frontend/message.hpp
+++ b/drape_frontend/message.hpp
@@ -36,12 +36,10 @@ public:
SelectObject,
GetSelectedObject,
GetMyPosition,
- AddRoute,
- CacheRouteSign,
+ AddRouteSegment,
+ RemoveRouteSegment,
CacheRouteArrows,
- RemoveRoute,
FlushRoute,
- FlushRouteSign,
FlushRouteArrows,
FollowRoute,
DeactivateRouteFollowing,
diff --git a/drape_frontend/message_subclasses.hpp b/drape_frontend/message_subclasses.hpp
index e162819127..f9e7f2700a 100644
--- a/drape_frontend/message_subclasses.hpp
+++ b/drape_frontend/message_subclasses.hpp
@@ -602,109 +602,72 @@ private:
bool & m_hasPosition;
};
-class AddRouteMessage : public Message
+class AddRouteSegmentMessage : public Message
{
public:
- AddRouteMessage(m2::PolylineD const & routePolyline, vector<double> const & turns,
- df::ColorConstant color, vector<traffic::SpeedGroup> const & traffic,
- df::RoutePattern const & pattern)
- : AddRouteMessage(routePolyline, turns, color, traffic, pattern, -1 /* invalid recache id */)
+ AddRouteSegmentMessage(dp::DrapeID segmentId, drape_ptr<RouteSegment> && segment)
+ : AddRouteSegmentMessage(segmentId, std::move(segment), -1 /* invalid recache id */)
{}
- AddRouteMessage(m2::PolylineD const & routePolyline, vector<double> const & turns,
- df::ColorConstant color, vector<traffic::SpeedGroup> const & traffic,
- df::RoutePattern const & pattern, int recacheId)
- : m_routePolyline(routePolyline)
- , m_color(color)
- , m_turns(turns)
- , m_pattern(pattern)
- , m_traffic(traffic)
+ AddRouteSegmentMessage(dp::DrapeID segmentId, drape_ptr<RouteSegment> && segment,
+ int recacheId)
+ : m_segmentId(segmentId)
+ , m_segment(std::move(segment))
, m_recacheId(recacheId)
{}
- Type GetType() const override { return Message::AddRoute; }
+ Type GetType() const override { return Message::AddRouteSegment; }
- m2::PolylineD const & GetRoutePolyline() { return m_routePolyline; }
- df::ColorConstant GetColor() const { return m_color; }
- vector<double> const & GetTurns() const { return m_turns; }
- df::RoutePattern const & GetPattern() const { return m_pattern; }
- vector<traffic::SpeedGroup> const & GetTraffic() const { return m_traffic; }
+ dp::DrapeID GetSegmentId() const { return m_segmentId; };
+ drape_ptr<RouteSegment> && GetRouteSegment() { return std::move(m_segment); }
int GetRecacheId() const { return m_recacheId; }
private:
- m2::PolylineD m_routePolyline;
- df::ColorConstant m_color;
- vector<double> m_turns;
- df::RoutePattern m_pattern;
- vector<traffic::SpeedGroup> m_traffic;
- int const m_recacheId;
-};
-
-class CacheRouteSignMessage : public Message
-{
-public:
- CacheRouteSignMessage(m2::PointD const & pos, bool isStart, bool isValid)
- : CacheRouteSignMessage(pos, isStart, isValid, -1 /* invalid recache id */)
- {}
-
- CacheRouteSignMessage(m2::PointD const & pos, bool isStart, bool isValid, int recacheId)
- : m_position(pos)
- , m_isStart(isStart)
- , m_isValid(isValid)
- , m_recacheId(recacheId)
- {}
-
- Type GetType() const override { return Message::CacheRouteSign; }
-
- m2::PointD const & GetPosition() const { return m_position; }
- bool IsStart() const { return m_isStart; }
- bool IsValid() const { return m_isValid; }
- int GetRecacheId() const { return m_recacheId; }
-
-private:
- m2::PointD const m_position;
- bool const m_isStart;
- bool const m_isValid;
+ dp::DrapeID m_segmentId;
+ drape_ptr<RouteSegment> m_segment;
int const m_recacheId;
};
class CacheRouteArrowsMessage : public Message
{
public:
- CacheRouteArrowsMessage(int routeIndex, vector<ArrowBorders> const & borders)
- : CacheRouteArrowsMessage(routeIndex, borders, -1 /* invalid recache id */)
+ CacheRouteArrowsMessage(dp::DrapeID segmentId, std::vector<ArrowBorders> const & borders)
+ : CacheRouteArrowsMessage(segmentId, borders, -1 /* invalid recache id */)
{}
- CacheRouteArrowsMessage(int routeIndex, vector<ArrowBorders> const & borders, int recacheId)
- : m_routeIndex(routeIndex)
+ CacheRouteArrowsMessage(dp::DrapeID segmentId, std::vector<ArrowBorders> const & borders,
+ int recacheId)
+ : m_segmentId(segmentId)
, m_borders(borders)
, m_recacheId(recacheId)
{}
Type GetType() const override { return Message::CacheRouteArrows; }
-
- int GetRouteIndex() const { return m_routeIndex; }
- vector<ArrowBorders> const & GetBorders() const { return m_borders; }
+ dp::DrapeID GetSegmentId() const { return m_segmentId; }
+ std::vector<ArrowBorders> const & GetBorders() const { return m_borders; }
int GetRecacheId() const { return m_recacheId; }
private:
- int m_routeIndex;
- vector<ArrowBorders> m_borders;
+ dp::DrapeID m_segmentId;
+ std::vector<ArrowBorders> m_borders;
int const m_recacheId;
};
-class RemoveRouteMessage : public Message
+class RemoveRouteSegmentMessage : public Message
{
public:
- RemoveRouteMessage(bool deactivateFollowing)
- : m_deactivateFollowing(deactivateFollowing)
+ RemoveRouteSegmentMessage(dp::DrapeID segmentId, bool deactivateFollowing)
+ : m_segmentId(segmentId)
+ , m_deactivateFollowing(deactivateFollowing)
{}
- Type GetType() const override { return Message::RemoveRoute; }
+ Type GetType() const override { return Message::RemoveRouteSegment; }
+ dp::DrapeID GetSegmentId() const { return m_segmentId; }
bool NeedDeactivateFollowing() const { return m_deactivateFollowing; }
private:
+ dp::DrapeID m_segmentId;
bool m_deactivateFollowing;
};
@@ -712,13 +675,13 @@ class FlushRouteMessage : public Message
{
public:
FlushRouteMessage(drape_ptr<RouteData> && routeData)
- : m_routeData(move(routeData))
+ : m_routeData(std::move(routeData))
{}
Type GetType() const override { return Message::FlushRoute; }
- bool IsGLContextDependent() const override { return true; }
- drape_ptr<RouteData> && AcceptRouteData() { return move(m_routeData); }
+ bool IsGLContextDependent() const override { return true; }
+ drape_ptr<RouteData> && AcceptRouteData() { return std::move(m_routeData); }
private:
drape_ptr<RouteData> m_routeData;
@@ -728,33 +691,17 @@ class FlushRouteArrowsMessage : public Message
{
public:
FlushRouteArrowsMessage(drape_ptr<RouteArrowsData> && routeArrowsData)
- : m_routeArrowsData(move(routeArrowsData))
+ : m_routeArrowsData(std::move(routeArrowsData))
{}
Type GetType() const override { return Message::FlushRouteArrows; }
- drape_ptr<RouteArrowsData> && AcceptRouteArrowsData() { return move(m_routeArrowsData); }
+ drape_ptr<RouteArrowsData> && AcceptRouteArrowsData() { return std::move(m_routeArrowsData); }
private:
drape_ptr<RouteArrowsData> m_routeArrowsData;
};
-class FlushRouteSignMessage : public Message
-{
-public:
- FlushRouteSignMessage(drape_ptr<RouteSignData> && routeSignData)
- : m_routeSignData(move(routeSignData))
- {}
-
- Type GetType() const override { return Message::FlushRouteSign; }
- bool IsGLContextDependent() const override { return true; }
-
- drape_ptr<RouteSignData> && AcceptRouteSignData() { return move(m_routeSignData); }
-
-private:
- drape_ptr<RouteSignData> m_routeSignData;
-};
-
class UpdateMapStyleMessage : public BaseBlockingMessage
{
public:
diff --git a/drape_frontend/route_builder.cpp b/drape_frontend/route_builder.cpp
index 9d13b149f5..3c79e67401 100644
--- a/drape_frontend/route_builder.cpp
+++ b/drape_frontend/route_builder.cpp
@@ -4,37 +4,28 @@
namespace df
{
-
RouteBuilder::RouteBuilder(TFlushRouteFn const & flushRouteFn,
- TFlushRouteSignFn const & flushRouteSignFn,
TFlushRouteArrowsFn const & flushRouteArrowsFn)
: m_flushRouteFn(flushRouteFn)
- , m_flushRouteSignFn(flushRouteSignFn)
, m_flushRouteArrowsFn(flushRouteArrowsFn)
{}
-void RouteBuilder::Build(m2::PolylineD const & routePolyline, vector<double> const & turns,
- df::ColorConstant color, vector<traffic::SpeedGroup> const & traffic,
- df::RoutePattern const & pattern, ref_ptr<dp::TextureManager> textures,
- int recacheId)
+void RouteBuilder::Build(dp::DrapeID segmentId, drape_ptr<RouteSegment> && segment,
+ ref_ptr<dp::TextureManager> textures, int recacheId)
{
drape_ptr<RouteData> routeData = make_unique_dp<RouteData>();
- routeData->m_routeIndex = m_routeIndex++;
- routeData->m_color = color;
- routeData->m_sourcePolyline = routePolyline;
- routeData->m_sourceTurns = turns;
- routeData->m_traffic = traffic;
- routeData->m_pattern = pattern;
- routeData->m_pivot = routePolyline.GetLimitRect().Center();
+ routeData->m_segmentId = segmentId;
+ routeData->m_segment = std::move(segment);
+ routeData->m_pivot = routeData->m_segment->m_polyline.GetLimitRect().Center();
routeData->m_recacheId = recacheId;
RouteShape::CacheRoute(textures, *routeData.get());
- m_routeCache.insert(make_pair(routeData->m_routeIndex, routePolyline));
+ m_routeCache.insert(std::make_pair(segmentId, routeData->m_segment->m_polyline));
// Flush route geometry.
GLFunctions::glFlush();
if (m_flushRouteFn != nullptr)
- m_flushRouteFn(move(routeData));
+ m_flushRouteFn(std::move(routeData));
}
void RouteBuilder::ClearRouteCache()
@@ -42,32 +33,15 @@ void RouteBuilder::ClearRouteCache()
m_routeCache.clear();
}
-void RouteBuilder::BuildSign(m2::PointD const & pos, bool isStart, bool isValid,
- ref_ptr<dp::TextureManager> textures, int recacheId)
-{
- drape_ptr<RouteSignData> routeSignData = make_unique_dp<RouteSignData>();
- routeSignData->m_isStart = isStart;
- routeSignData->m_position = pos;
- routeSignData->m_isValid = isValid;
- routeSignData->m_recacheId = recacheId;
- if (isValid)
- RouteShape::CacheRouteSign(textures, *routeSignData.get());
-
- // Flush route sign geometry.
- GLFunctions::glFlush();
-
- if (m_flushRouteSignFn != nullptr)
- m_flushRouteSignFn(move(routeSignData));
-}
-
-void RouteBuilder::BuildArrows(int routeIndex, vector<ArrowBorders> const & borders,
+void RouteBuilder::BuildArrows(dp::DrapeID segmentId, std::vector<ArrowBorders> const & borders,
ref_ptr<dp::TextureManager> textures, int recacheId)
{
- auto it = m_routeCache.find(routeIndex);
+ auto it = m_routeCache.find(segmentId);
if (it == m_routeCache.end())
return;
drape_ptr<RouteArrowsData> routeArrowsData = make_unique_dp<RouteArrowsData>();
+ routeArrowsData->m_segmentId = segmentId;
routeArrowsData->m_pivot = it->second.GetLimitRect().Center();
routeArrowsData->m_recacheId = recacheId;
RouteShape::CacheRouteArrows(textures, it->second, borders, *routeArrowsData.get());
@@ -76,7 +50,6 @@ void RouteBuilder::BuildArrows(int routeIndex, vector<ArrowBorders> const & bord
GLFunctions::glFlush();
if (m_flushRouteArrowsFn != nullptr)
- m_flushRouteArrowsFn(move(routeArrowsData));
+ m_flushRouteArrowsFn(std::move(routeArrowsData));
}
-
-} // namespace df
+} // namespace df
diff --git a/drape_frontend/route_builder.hpp b/drape_frontend/route_builder.hpp
index f229cfd888..2067e96d45 100644
--- a/drape_frontend/route_builder.hpp
+++ b/drape_frontend/route_builder.hpp
@@ -10,43 +10,33 @@
#include "geometry/polyline2d.hpp"
-#include "std/function.hpp"
-#include "std/unordered_map.hpp"
+#include <functional>
+#include <unordered_map>
+#include <vector>
namespace df
{
-
class RouteBuilder
{
public:
using TFlushRouteFn = function<void(drape_ptr<RouteData> &&)>;
- using TFlushRouteSignFn = function<void(drape_ptr<RouteSignData> &&)>;
using TFlushRouteArrowsFn = function<void(drape_ptr<RouteArrowsData> &&)>;
RouteBuilder(TFlushRouteFn const & flushRouteFn,
- TFlushRouteSignFn const & flushRouteSignFn,
TFlushRouteArrowsFn const & flushRouteArrowsFn);
- void Build(m2::PolylineD const & routePolyline, vector<double> const & turns,
- df::ColorConstant color, vector<traffic::SpeedGroup> const & traffic,
- df::RoutePattern const & pattern, ref_ptr<dp::TextureManager> textures,
- int recacheId);
+ void Build(dp::DrapeID segmentId, drape_ptr<RouteSegment> && segment,
+ ref_ptr<dp::TextureManager> textures, int recacheId);
- void BuildArrows(int routeIndex, vector<ArrowBorders> const & borders,
+ void BuildArrows(dp::DrapeID segmentId, std::vector<ArrowBorders> const & borders,
ref_ptr<dp::TextureManager> textures, int recacheId);
- void BuildSign(m2::PointD const & pos, bool isStart, bool isValid,
- ref_ptr<dp::TextureManager> textures, int recacheId);
-
void ClearRouteCache();
private:
TFlushRouteFn m_flushRouteFn;
- TFlushRouteSignFn m_flushRouteSignFn;
TFlushRouteArrowsFn m_flushRouteArrowsFn;
- int m_routeIndex = 0;
- unordered_map<int, m2::PolylineD> m_routeCache;
+ std::unordered_map<dp::DrapeID, m2::PolylineD> m_routeCache;
};
-
-} // namespace df
+} // namespace df
diff --git a/drape_frontend/route_renderer.cpp b/drape_frontend/route_renderer.cpp
index 1a681afc6d..872cdfd034 100644
--- a/drape_frontend/route_renderer.cpp
+++ b/drape_frontend/route_renderer.cpp
@@ -8,14 +8,14 @@
#include "drape/utils/projection.hpp"
#include "drape/vertex_array_buffer.hpp"
-#include "indexer/map_style_reader.hpp"
#include "indexer/scales.hpp"
#include "base/logging.hpp"
+#include <algorithm>
+
namespace df
{
-
std::string const kRouteColor = "Route";
std::string const kRouteOutlineColor = "RouteOutline";
std::string const kRoutePedestrian = "RoutePedestrian";
@@ -23,8 +23,7 @@ std::string const kRouteBicycle = "RouteBicycle";
namespace
{
-
-float const kHalfWidthInPixelVehicle[] =
+float const kHalfWidthInPixelCar[] =
{
// 1 2 3 4 5 6 7 8 9 10
1.0f, 1.0f, 1.5f, 1.5f, 1.5f, 2.0f, 2.0f, 2.0f, 2.5f, 2.5f,
@@ -43,31 +42,31 @@ float const kHalfWidthInPixelOthers[] =
int const kArrowAppearingZoomLevel = 14;
int const kInvalidGroup = -1;
-void ClipBorders(vector<ArrowBorders> & borders)
+void ClipBorders(std::vector<ArrowBorders> & borders)
{
auto invalidBorders = [](ArrowBorders const & borders)
{
return borders.m_groupIndex == kInvalidGroup;
};
- borders.erase(remove_if(borders.begin(), borders.end(), invalidBorders), borders.end());
+ borders.erase(std::remove_if(borders.begin(), borders.end(), invalidBorders), borders.end());
}
-void MergeAndClipBorders(vector<ArrowBorders> & borders)
+void MergeAndClipBorders(std::vector<ArrowBorders> & borders)
{
- // initial clipping
+ // Initial clipping.
ClipBorders(borders);
if (borders.empty())
return;
- // mark groups
+ // Mark groups.
for (size_t i = 0; i + 1 < borders.size(); i++)
{
if (borders[i].m_endDistance >= borders[i + 1].m_startDistance)
borders[i + 1].m_groupIndex = borders[i].m_groupIndex;
}
- // merge groups
+ // Merge groups.
int lastGroup = borders.front().m_groupIndex;
size_t lastGroupIndex = 0;
for (size_t i = 1; i < borders.size(); i++)
@@ -85,17 +84,12 @@ void MergeAndClipBorders(vector<ArrowBorders> & borders)
}
borders[lastGroupIndex].m_endDistance = borders.back().m_endDistance;
- // clip groups
+ // Clip groups.
ClipBorders(borders);
}
-void BuildBuckets(RouteRenderProperty const & renderProperty, ref_ptr<dp::GpuProgramManager> mng)
-{
- for (drape_ptr<dp::RenderBucket> const & bucket : renderProperty.m_buckets)
- bucket->GetBuffer()->Build(mng->GetProgram(renderProperty.m_state.GetProgramIndex()));
-}
-
-bool AreEqualArrowBorders(vector<ArrowBorders> const & borders1, vector<ArrowBorders> const & borders2)
+bool AreEqualArrowBorders(std::vector<ArrowBorders> const & borders1,
+ std::vector<ArrowBorders> const & borders2)
{
if (borders1.size() != borders2.size())
return false;
@@ -119,28 +113,105 @@ bool AreEqualArrowBorders(vector<ArrowBorders> const & borders1, vector<ArrowBor
return true;
}
-dp::Color GetOutlineColor(df::ColorConstant const & routeColor)
+std::vector<ArrowBorders> CalculateArrowBorders(ScreenBase const & screen, float currentHalfWidth,
+ drape_ptr<RouteData> const & routeData,
+ double distanceFromBegin)
{
- return df::GetColorConstant(routeColor == kRouteColor ? kRouteOutlineColor : routeColor);
+ if (routeData->m_segment->m_turns.empty())
+ return {};
+
+ // Calculate arrow mercator length.
+ double glbHalfLen = 0.5 * kArrowSize;
+ double const glbHalfTextureWidth = currentHalfWidth * kArrowHeightFactor * screen.GetScale();
+ double const glbHalfTextureLen = glbHalfTextureWidth * kArrowAspect;
+ if (glbHalfLen < glbHalfTextureLen)
+ glbHalfLen = glbHalfTextureLen;
+
+ double const glbArrowHead = 2.0 * kArrowHeadSize * glbHalfTextureLen;
+ double const glbArrowTail = 2.0 * kArrowTailSize * glbHalfTextureLen;
+ double const glbMinArrowSize = glbArrowHead + glbArrowTail;
+
+ double const kExtendCoef = 1.1;
+ m2::RectD screenRect = screen.ClipRect();
+ screenRect.Scale(kExtendCoef);
+
+ auto const & segment = routeData->m_segment;
+
+ // Calculate arrow borders.
+ std::vector<ArrowBorders> newArrowBorders;
+ newArrowBorders.reserve(segment->m_turns.size());
+ for (size_t i = 0; i < segment->m_turns.size(); i++)
+ {
+ ArrowBorders arrowBorders;
+ arrowBorders.m_groupIndex = static_cast<int>(i);
+ arrowBorders.m_startDistance = std::max(0.0, segment->m_turns[i] - glbHalfLen * 0.8);
+ arrowBorders.m_endDistance = std::min(routeData->m_length, segment->m_turns[i] + glbHalfLen * 1.2);
+
+ if ((arrowBorders.m_endDistance - arrowBorders.m_startDistance) < glbMinArrowSize ||
+ arrowBorders.m_startDistance < distanceFromBegin)
+ {
+ continue;
+ }
+
+ m2::PointD pt = segment->m_polyline.GetPointByDistance(arrowBorders.m_startDistance);
+ if (screenRect.IsPointInside(pt))
+ {
+ newArrowBorders.push_back(arrowBorders);
+ continue;
+ }
+
+ pt = segment->m_polyline.GetPointByDistance(arrowBorders.m_endDistance);
+ if (screenRect.IsPointInside(pt))
+ {
+ newArrowBorders.push_back(arrowBorders);
+ continue;
+ }
+ }
+
+ // Merge intersected borders and clip them.
+ MergeAndClipBorders(newArrowBorders);
+
+ // Process head and tail.
+ for (ArrowBorders & borders : newArrowBorders)
+ {
+ borders.m_startDistance += glbArrowTail;
+ borders.m_endDistance -= glbArrowHead;
+ }
+
+ return newArrowBorders;
}
-} // namespace
+void BuildBuckets(RouteRenderProperty const & renderProperty, ref_ptr<dp::GpuProgramManager> mng)
+{
+ for (auto const & bucket : renderProperty.m_buckets)
+ bucket->GetBuffer()->Build(mng->GetProgram(renderProperty.m_state.GetProgramIndex()));
+}
+
+dp::Color GetOutlineColor(drape_ptr<RouteSegment> const & routeSegment)
+{
+ if (routeSegment->m_routeType == RouteType::Car || routeSegment->m_routeType == RouteType::Taxi)
+ return df::GetColorConstant(kRouteOutlineColor);
+
+ return df::GetColorConstant(routeSegment->m_color);
+}
+} // namespace
RouteRenderer::RouteRenderer()
: m_distanceFromBegin(0.0)
+ , m_followingEnabled(false)
{}
-void RouteRenderer::InterpolateByZoom(ScreenBase const & screen, ColorConstant color,
+void RouteRenderer::InterpolateByZoom(drape_ptr<RouteSegment> const & routeSegment, ScreenBase const & screen,
float & halfWidth, double & zoom) const
{
double const zoomLevel = GetZoomLevel(screen.GetScale());
zoom = trunc(zoomLevel);
- int const index = zoom - 1.0;
- float const lerpCoef = zoomLevel - zoom;
+ int const index = static_cast<int>(zoom - 1.0);
+ float const lerpCoef = static_cast<float>(zoomLevel - zoom);
- float const * halfWidthInPixel = kHalfWidthInPixelVehicle;
- if (color != kRouteColor)
- halfWidthInPixel = kHalfWidthInPixelOthers;
+ float const * halfWidthInPixel = kHalfWidthInPixelOthers;
+ if (routeSegment->m_routeType == RouteType::Car || routeSegment->m_routeType == RouteType::Taxi)
+ halfWidthInPixel = kHalfWidthInPixelCar;
if (index < scales::UPPER_STYLE_SCALE)
halfWidth = halfWidthInPixel[index] + lerpCoef * (halfWidthInPixel[index + 1] - halfWidthInPixel[index]);
@@ -153,272 +224,192 @@ void RouteRenderer::InterpolateByZoom(ScreenBase const & screen, ColorConstant c
void RouteRenderer::UpdateRoute(ScreenBase const & screen, TCacheRouteArrowsCallback const & callback)
{
ASSERT(callback != nullptr, ());
-
- if (!m_routeData)
- return;
-
- // Interpolate values by zoom level.
- double zoom = 0.0;
- InterpolateByZoom(screen, m_routeData->m_color, m_currentHalfWidth, zoom);
-
- // Update arrows.
- if (zoom >= kArrowAppearingZoomLevel && !m_routeData->m_sourceTurns.empty())
+ for (auto const & routeData : m_routeData)
{
- // Calculate arrow mercator length.
- double glbHalfLen = 0.5 * kArrowSize;
- double const glbHalfTextureWidth = m_currentHalfWidth * kArrowHeightFactor * screen.GetScale();
- double const glbHalfTextureLen = glbHalfTextureWidth * kArrowAspect;
- if (glbHalfLen < glbHalfTextureLen)
- glbHalfLen = glbHalfTextureLen;
-
- double const glbArrowHead = 2.0 * kArrowHeadSize * glbHalfTextureLen;
- double const glbArrowTail = 2.0 * kArrowTailSize * glbHalfTextureLen;
- double const glbMinArrowSize = glbArrowHead + glbArrowTail;
-
- double const kExtendCoef = 1.1;
- m2::RectD screenRect = screen.ClipRect();
- screenRect.Scale(kExtendCoef);
-
- // Calculate arrow borders.
- vector<ArrowBorders> newArrowBorders;
- newArrowBorders.reserve(m_routeData->m_sourceTurns.size());
- for (size_t i = 0; i < m_routeData->m_sourceTurns.size(); i++)
- {
- ArrowBorders arrowBorders;
- arrowBorders.m_groupIndex = static_cast<int>(i);
- arrowBorders.m_startDistance = max(0.0, m_routeData->m_sourceTurns[i] - glbHalfLen * 0.8);
- arrowBorders.m_endDistance = min(m_routeData->m_length, m_routeData->m_sourceTurns[i] + glbHalfLen * 1.2);
-
- if ((arrowBorders.m_endDistance - arrowBorders.m_startDistance) < glbMinArrowSize ||
- arrowBorders.m_startDistance < m_distanceFromBegin)
- continue;
-
- m2::PointD pt = m_routeData->m_sourcePolyline.GetPointByDistance(arrowBorders.m_startDistance);
- if (screenRect.IsPointInside(pt))
- {
- newArrowBorders.push_back(arrowBorders);
- continue;
- }
-
- pt = m_routeData->m_sourcePolyline.GetPointByDistance(arrowBorders.m_endDistance);
- if (screenRect.IsPointInside(pt))
- {
- newArrowBorders.push_back(arrowBorders);
- continue;
- }
- }
+ auto & additional = m_routeAdditional[routeData->m_segmentId];
- // Merge intersected borders and clip them.
- MergeAndClipBorders(newArrowBorders);
+ // Interpolate values by zoom level.
+ double zoom = 0.0;
+ float halfWidth = 0.0;
+ InterpolateByZoom(routeData->m_segment, screen, halfWidth, zoom);
+ additional.m_currentHalfWidth = halfWidth;
- // Process head and tail.
- for (ArrowBorders & borders : newArrowBorders)
+ if (zoom < kArrowAppearingZoomLevel)
{
- borders.m_startDistance += glbArrowTail;
- borders.m_endDistance -= glbArrowHead;
+ additional.m_arrowsData.reset();
+ additional.m_arrowBorders.clear();
+ continue;
}
+ // Calculate arrow borders.
+ auto newArrowBorders = CalculateArrowBorders(screen, halfWidth, routeData,
+ m_followingEnabled ? m_distanceFromBegin : -1.0f);
if (newArrowBorders.empty())
{
// Clear arrows.
- m_arrowBorders.clear();
- m_routeArrows.reset();
+ additional.m_arrowsData.reset();
+ additional.m_arrowBorders.clear();
}
- else if (!AreEqualArrowBorders(newArrowBorders, m_arrowBorders))
+ else if (!AreEqualArrowBorders(newArrowBorders, additional.m_arrowBorders))
{
- m_arrowBorders = move(newArrowBorders);
- callback(m_routeData->m_routeIndex, m_arrowBorders);
+ additional.m_arrowBorders = std::move(newArrowBorders);
+ callback(routeData->m_segmentId, additional.m_arrowBorders);
}
}
- else
- {
- m_routeArrows.reset();
- }
}
-void RouteRenderer::RenderRoute(ScreenBase const & screen, bool trafficShown,
- ref_ptr<dp::GpuProgramManager> mng,
- dp::UniformValuesStorage const & commonUniforms)
+void RouteRenderer::RenderRouteData(drape_ptr<RouteData> const & routeData,
+ ScreenBase const & screen, bool trafficShown,
+ ref_ptr<dp::GpuProgramManager> mng,
+ dp::UniformValuesStorage const & commonUniforms)
{
- if (!m_routeData || m_routeData->m_route.m_buckets.empty())
+ if (routeData->m_renderProperty.m_buckets.empty())
return;
- // Render route.
- {
- dp::GLState const & state = m_routeData->m_route.m_state;
-
- // Set up uniforms.
- dp::UniformValuesStorage uniforms = commonUniforms;
- math::Matrix<float, 4, 4> mv = screen.GetModelView(m_routeData->m_pivot, kShapeCoordScalar);
- uniforms.SetMatrix4x4Value("modelView", mv.m_data);
- glsl::vec4 const color = glsl::ToVec4(df::GetColorConstant(m_routeData->m_color));
- uniforms.SetFloatValue("u_color", color.r, color.g, color.b, color.a);
- double const screenScale = screen.GetScale();
- uniforms.SetFloatValue("u_routeParams", m_currentHalfWidth, m_currentHalfWidth * screenScale,
- m_distanceFromBegin, trafficShown ? 1.0f : 0.0f);
-
- if (m_routeData->m_pattern.m_isDashed)
- {
- uniforms.SetFloatValue("u_pattern", m_currentHalfWidth * m_routeData->m_pattern.m_dashLength * screenScale,
- m_currentHalfWidth * m_routeData->m_pattern.m_gapLength * screenScale);
- }
- else
- {
- glsl::vec4 const outlineColor = glsl::ToVec4(GetOutlineColor(m_routeData->m_color));
- uniforms.SetFloatValue("u_outlineColor", outlineColor.r, outlineColor.g, outlineColor.b, outlineColor.a);
- }
+ float const currentHalfWidth = m_routeAdditional[routeData->m_segmentId].m_currentHalfWidth;
+ float const screenHalfWidth = static_cast<float>(currentHalfWidth * screen.GetScale());
+ float const dist = m_followingEnabled ? static_cast<float>(m_distanceFromBegin) : -1.0f;
- // Set up shaders and apply uniforms.
- ref_ptr<dp::GpuProgram> prg = mng->GetProgram(m_routeData->m_pattern.m_isDashed ?
- gpu::ROUTE_DASH_PROGRAM : gpu::ROUTE_PROGRAM);
- prg->Bind();
- dp::ApplyState(state, prg);
- dp::ApplyUniforms(uniforms, prg);
+ dp::GLState const & state = routeData->m_renderProperty.m_state;
+ auto const & segment = routeData->m_segment;
- // Render buckets.
- for (drape_ptr<dp::RenderBucket> const & bucket : m_routeData->m_route.m_buckets)
- bucket->Render(state.GetDrawAsLine());
- }
+ // Set up uniforms.
+ dp::UniformValuesStorage uniforms = commonUniforms;
+ math::Matrix<float, 4, 4> mv = screen.GetModelView(routeData->m_pivot, kShapeCoordScalar);
+ uniforms.SetMatrix4x4Value("modelView", mv.m_data);
- // Render arrows.
- if (m_routeArrows != nullptr)
- {
- dp::GLState const & state = m_routeArrows->m_arrows.m_state;
-
- // set up shaders and apply common uniforms
- dp::UniformValuesStorage uniforms = commonUniforms;
- math::Matrix<float, 4, 4> mv = screen.GetModelView(m_routeArrows->m_pivot, kShapeCoordScalar);
- uniforms.SetMatrix4x4Value("modelView", mv.m_data);
- uniforms.SetFloatValue("u_arrowHalfWidth", m_currentHalfWidth * kArrowHeightFactor);
- uniforms.SetFloatValue("u_opacity", 1.0f);
-
- ref_ptr<dp::GpuProgram> prg = mng->GetProgram(gpu::ROUTE_ARROW_PROGRAM);
- prg->Bind();
- dp::ApplyState(state, prg);
- dp::ApplyUniforms(uniforms, prg);
- for (drape_ptr<dp::RenderBucket> const & bucket : m_routeArrows->m_arrows.m_buckets)
- bucket->Render(state.GetDrawAsLine());
- }
-}
+ glsl::vec4 const color = glsl::ToVec4(df::GetColorConstant(segment->m_color));
+ uniforms.SetFloatValue("u_color", color.r, color.g, color.b, color.a);
-void RouteRenderer::RenderRouteSigns(ScreenBase const & screen, ref_ptr<dp::GpuProgramManager> mng,
- dp::UniformValuesStorage const & commonUniforms)
-{
- if (m_startRouteSign)
+ uniforms.SetFloatValue("u_routeParams", currentHalfWidth, screenHalfWidth, dist,
+ trafficShown ? 1.0f : 0.0f);
+
+ if (segment->m_pattern.m_isDashed)
{
- ASSERT(m_startRouteSign->m_isValid, ());
- RenderRouteSign(m_startRouteSign, screen, mng, commonUniforms);
+ uniforms.SetFloatValue("u_pattern",
+ static_cast<float>(screenHalfWidth * segment->m_pattern.m_dashLength),
+ static_cast<float>(screenHalfWidth * segment->m_pattern.m_gapLength));
}
-
- if (m_finishRouteSign)
+ else
{
- ASSERT(m_finishRouteSign->m_isValid, ());
- RenderRouteSign(m_finishRouteSign, screen, mng, commonUniforms);
+ glsl::vec4 const outlineColor = glsl::ToVec4(GetOutlineColor(segment));
+ uniforms.SetFloatValue("u_outlineColor", outlineColor.r, outlineColor.g,
+ outlineColor.b, outlineColor.a);
}
+
+ // Set up shaders and apply uniforms.
+ ref_ptr<dp::GpuProgram> prg = mng->GetProgram(segment->m_pattern.m_isDashed ?
+ gpu::ROUTE_DASH_PROGRAM : gpu::ROUTE_PROGRAM);
+ prg->Bind();
+ dp::ApplyState(state, prg);
+ dp::ApplyUniforms(uniforms, prg);
+
+ // Render buckets.
+ for (auto const & bucket : routeData->m_renderProperty.m_buckets)
+ bucket->Render(state.GetDrawAsLine());
}
-void RouteRenderer::RenderRouteSign(drape_ptr<RouteSignData> const & sign, ScreenBase const & screen,
- ref_ptr<dp::GpuProgramManager> mng,
- dp::UniformValuesStorage const & commonUniforms)
+void RouteRenderer::RenderRouteArrowData(dp::DrapeID segmentId, RouteAdditional const & routeAdditional,
+ ScreenBase const & screen, ref_ptr<dp::GpuProgramManager> mng,
+ dp::UniformValuesStorage const & commonUniforms)
{
- if (sign->m_sign.m_buckets.empty())
+ if (routeAdditional.m_arrowsData == nullptr ||
+ routeAdditional.m_arrowsData->m_renderProperty.m_buckets.empty())
+ {
return;
+ }
- dp::GLState const & state = sign->m_sign.m_state;
+ float const currentHalfWidth = m_routeAdditional[segmentId].m_currentHalfWidth;
+ dp::GLState const & state = routeAdditional.m_arrowsData->m_renderProperty.m_state;
+
+ // Set up shaders and apply common uniforms.
dp::UniformValuesStorage uniforms = commonUniforms;
- math::Matrix<float, 4, 4> mv = screen.GetModelView(sign->m_position, 1.0);
+ math::Matrix<float, 4, 4> mv = screen.GetModelView(routeAdditional.m_arrowsData->m_pivot,
+ kShapeCoordScalar);
uniforms.SetMatrix4x4Value("modelView", mv.m_data);
+ uniforms.SetFloatValue("u_arrowHalfWidth", static_cast<float>(currentHalfWidth * kArrowHeightFactor));
uniforms.SetFloatValue("u_opacity", 1.0f);
- ref_ptr<dp::GpuProgram> program = screen.isPerspective() ? mng->GetProgram(state.GetProgram3dIndex())
- : mng->GetProgram(state.GetProgramIndex());
- program->Bind();
-
- dp::ApplyState(state, program);
- dp::ApplyUniforms(uniforms, program);
-
- for (auto const & bucket : sign->m_sign.m_buckets)
- {
- bucket->GetBuffer()->Build(program);
+ ref_ptr<dp::GpuProgram> prg = mng->GetProgram(gpu::ROUTE_ARROW_PROGRAM);
+ prg->Bind();
+ dp::ApplyState(state, prg);
+ dp::ApplyUniforms(uniforms, prg);
+ for (auto const & bucket : routeAdditional.m_arrowsData->m_renderProperty.m_buckets)
bucket->Render(state.GetDrawAsLine());
- }
}
-void RouteRenderer::SetRouteData(drape_ptr<RouteData> && routeData, ref_ptr<dp::GpuProgramManager> mng)
+void RouteRenderer::RenderRoute(ScreenBase const & screen, bool trafficShown,
+ ref_ptr<dp::GpuProgramManager> mng,
+ dp::UniformValuesStorage const & commonUniforms)
{
- m_routeData = move(routeData);
- m_arrowBorders.clear();
+ if (m_routeData.empty())
+ return;
- BuildBuckets(m_routeData->m_route, mng);
+ // Render route.
+ for (auto const & routeData : m_routeData)
+ RenderRouteData(routeData, screen, trafficShown, mng, commonUniforms);
+
+ // Render arrows.
+ for (auto const & p : m_routeAdditional)
+ RenderRouteArrowData(p.first, p.second, screen, mng, commonUniforms);
}
-void RouteRenderer::SetRouteSign(drape_ptr<RouteSignData> && routeSignData, ref_ptr<dp::GpuProgramManager> mng)
+void RouteRenderer::AddRouteData(drape_ptr<RouteData> && routeData,
+ ref_ptr<dp::GpuProgramManager> mng)
{
- if (routeSignData->m_isStart)
- {
- if (!routeSignData->m_isValid)
- {
- m_startRouteSign.reset();
- return;
- }
-
- m_startRouteSign = move(routeSignData);
- BuildBuckets(m_startRouteSign->m_sign, mng);
- }
- else
- {
- if (!routeSignData->m_isValid)
- {
- m_finishRouteSign.reset();
- return;
- }
+ // Remove old route data with the same id.
+ RemoveRouteData(routeData->m_segmentId);
- m_finishRouteSign = move(routeSignData);
- BuildBuckets(m_finishRouteSign->m_sign, mng);
- }
+ // Add new route data.
+ m_routeData.push_back(std::move(routeData));
+ BuildBuckets(m_routeData.back()->m_renderProperty, mng);
}
-drape_ptr<RouteSignData> const & RouteRenderer::GetStartPoint() const
+std::vector<drape_ptr<RouteData>> const & RouteRenderer::GetRouteData() const
{
- return m_startRouteSign;
+ return m_routeData;
}
-drape_ptr<RouteSignData> const & RouteRenderer::GetFinishPoint() const
+void RouteRenderer::RemoveRouteData(dp::DrapeID segmentId)
{
- return m_finishRouteSign;
+ auto const functor = [&segmentId](drape_ptr<RouteData> const & data)
+ {
+ return data->m_segmentId == segmentId;
+ };
+ m_routeData.erase(std::remove_if(m_routeData.begin(), m_routeData.end(), functor),
+ m_routeData.end());
+ m_routeAdditional[segmentId].m_arrowsData.reset();
+ m_routeAdditional[segmentId].m_arrowBorders.clear();
}
-drape_ptr<RouteData> const & RouteRenderer::GetRouteData() const
+void RouteRenderer::AddRouteArrowsData(drape_ptr<RouteArrowsData> && routeArrowsData,
+ ref_ptr<dp::GpuProgramManager> mng)
{
- return m_routeData;
+ auto & additional = m_routeAdditional[routeArrowsData->m_segmentId];
+ additional.m_arrowsData = std::move(routeArrowsData);
+ BuildBuckets(additional.m_arrowsData->m_renderProperty, mng);
}
-void RouteRenderer::SetRouteArrows(drape_ptr<RouteArrowsData> && routeArrowsData,
- ref_ptr<dp::GpuProgramManager> mng)
+void RouteRenderer::ClearRouteData()
{
- m_routeArrows = move(routeArrowsData);
- BuildBuckets(m_routeArrows->m_arrows, mng);
+ m_routeData.clear();
+ m_routeAdditional.clear();
}
void RouteRenderer::Clear()
{
- m_routeData.reset();
- m_startRouteSign.reset();
- m_finishRouteSign.reset();
- m_arrowBorders.clear();
- m_routeArrows.reset();
+ ClearRouteData();
m_distanceFromBegin = 0.0;
}
void RouteRenderer::ClearGLDependentResources()
{
- if (m_routeData != nullptr)
- m_routeData->m_route = RouteRenderProperty();
- if (m_startRouteSign != nullptr)
- m_startRouteSign->m_sign = RouteRenderProperty();
- if (m_finishRouteSign != nullptr)
- m_finishRouteSign->m_sign = RouteRenderProperty();
- m_routeArrows.reset();
+ // Here we clear only GL-dependent part of route data.
+ for (auto & routeData : m_routeData)
+ routeData->m_renderProperty = RouteRenderProperty();
+
+ // All additional data (like arrows) will be regenerated, so clear them all.
+ m_routeAdditional.clear();
}
void RouteRenderer::UpdateDistanceFromBegin(double distanceFromBegin)
@@ -426,4 +417,8 @@ void RouteRenderer::UpdateDistanceFromBegin(double distanceFromBegin)
m_distanceFromBegin = distanceFromBegin;
}
-} // namespace df
+void RouteRenderer::SetFollowingEnabled(bool enabled)
+{
+ m_followingEnabled = enabled;
+}
+} // namespace df
diff --git a/drape_frontend/route_renderer.hpp b/drape_frontend/route_renderer.hpp
index 025b76f66a..2a0ff6167f 100644
--- a/drape_frontend/route_renderer.hpp
+++ b/drape_frontend/route_renderer.hpp
@@ -2,16 +2,19 @@
#include "drape_frontend/route_builder.hpp"
+#include "drape/drape_global.hpp"
#include "drape/gpu_program_manager.hpp"
#include "drape/pointers.hpp"
#include "geometry/screenbase.hpp"
+#include <functional>
#include <string>
+#include <vector>
+#include <unordered_map>
namespace df
{
-
extern std::string const kRouteColor;
extern std::string const kRouteOutlineColor;
extern std::string const kRoutePedestrian;
@@ -20,49 +23,50 @@ extern std::string const kRouteBicycle;
class RouteRenderer final
{
public:
- using TCacheRouteArrowsCallback = function<void(int, vector<ArrowBorders> const &)>;
+ using TCacheRouteArrowsCallback = std::function<void(dp::DrapeID, std::vector<ArrowBorders> const &)>;
RouteRenderer();
void UpdateRoute(ScreenBase const & screen, TCacheRouteArrowsCallback const & callback);
- void RenderRoute(ScreenBase const & screen, bool trafficShown,
- ref_ptr<dp::GpuProgramManager> mng,
+ void RenderRoute(ScreenBase const & screen, bool trafficShown, ref_ptr<dp::GpuProgramManager> mng,
dp::UniformValuesStorage const & commonUniforms);
- void RenderRouteSigns(ScreenBase const & screen, ref_ptr<dp::GpuProgramManager> mng,
- dp::UniformValuesStorage const & commonUniforms);
-
- void SetRouteData(drape_ptr<RouteData> && routeData, ref_ptr<dp::GpuProgramManager> mng);
- drape_ptr<RouteData> const & GetRouteData() const;
+ void AddRouteData(drape_ptr<RouteData> && routeData, ref_ptr<dp::GpuProgramManager> mng);
+ std::vector<drape_ptr<RouteData>> const & GetRouteData() const;
- void SetRouteSign(drape_ptr<RouteSignData> && routeSignData, ref_ptr<dp::GpuProgramManager> mng);
- drape_ptr<RouteSignData> const & GetStartPoint() const;
- drape_ptr<RouteSignData> const & GetFinishPoint() const;
+ void RemoveRouteData(dp::DrapeID segmentId);
- void SetRouteArrows(drape_ptr<RouteArrowsData> && routeArrowsData, ref_ptr<dp::GpuProgramManager> mng);
+ void AddRouteArrowsData(drape_ptr<RouteArrowsData> && routeArrowsData,
+ ref_ptr<dp::GpuProgramManager> mng);
void Clear();
+ void ClearRouteData();
void ClearGLDependentResources();
void UpdateDistanceFromBegin(double distanceFromBegin);
+ void SetFollowingEnabled(bool enabled);
private:
- void InterpolateByZoom(ScreenBase const & screen, ColorConstant color,
+ struct RouteAdditional
+ {
+ drape_ptr<RouteArrowsData> m_arrowsData;
+ std::vector<ArrowBorders> m_arrowBorders;
+ float m_currentHalfWidth = 0.0f;
+ };
+
+ void InterpolateByZoom(drape_ptr<RouteSegment> const & routeSegment, ScreenBase const & screen,
float & halfWidth, double & zoom) const;
- void RenderRouteSign(drape_ptr<RouteSignData> const & sign, ScreenBase const & screen,
- ref_ptr<dp::GpuProgramManager> mng, dp::UniformValuesStorage const & commonUniforms);
+ void RenderRouteData(drape_ptr<RouteData> const & routeData, ScreenBase const & screen,
+ bool trafficShown, ref_ptr<dp::GpuProgramManager> mng,
+ dp::UniformValuesStorage const & commonUniforms);
+ void RenderRouteArrowData(dp::DrapeID segmentId, RouteAdditional const & routeAdditional,
+ ScreenBase const & screen, ref_ptr<dp::GpuProgramManager> mng,
+ dp::UniformValuesStorage const & commonUniforms);
double m_distanceFromBegin;
- drape_ptr<RouteData> m_routeData;
-
- vector<ArrowBorders> m_arrowBorders;
- drape_ptr<RouteArrowsData> m_routeArrows;
-
- drape_ptr<RouteSignData> m_startRouteSign;
- drape_ptr<RouteSignData> m_finishRouteSign;
-
- float m_currentHalfWidth = 0.0f;
+ std::vector<drape_ptr<RouteData>> m_routeData;
+ std::unordered_map<dp::DrapeID, RouteAdditional> m_routeAdditional;
+ bool m_followingEnabled;
};
-
-} // namespace df
+} // namespace df
diff --git a/drape_frontend/route_shape.cpp b/drape_frontend/route_shape.cpp
index 9c78fba1eb..52a2bc7d8e 100644
--- a/drape_frontend/route_shape.cpp
+++ b/drape_frontend/route_shape.cpp
@@ -24,12 +24,14 @@ float const kRightSide = -1.0f;
float const kRouteDepth = 100.0f;
float const kArrowsDepth = 200.0f;
-void GetArrowTextureRegion(ref_ptr<dp::TextureManager> textures, dp::TextureManager::SymbolRegion & region)
+void GetArrowTextureRegion(ref_ptr<dp::TextureManager> textures,
+ dp::TextureManager::SymbolRegion & region)
{
textures->GetSymbolRegion("route-arrow", region);
}
-std::vector<m2::PointD> CalculatePoints(m2::PolylineD const & polyline, double start, double end)
+std::vector<m2::PointD> CalculatePoints(m2::PolylineD const & polyline,
+ double start, double end)
{
std::vector<m2::PointD> result;
result.reserve(polyline.GetSize() / 4);
@@ -77,18 +79,23 @@ std::vector<m2::PointD> CalculatePoints(m2::PolylineD const & polyline, double s
return result;
}
+float SideByNormal(glsl::vec2 const & normal, bool isLeft)
+{
+ float const kEps = 1e-5;
+ float const side = isLeft ? kLeftSide : kRightSide;
+ return glsl::length(normal) < kEps ? kCenter : side;
+}
+
void GenerateJoinsTriangles(glsl::vec3 const & pivot, std::vector<glsl::vec2> const & normals,
glsl::vec4 const & color, glsl::vec2 const & length, bool isLeft,
RouteShape::TGeometryBuffer & joinsGeometry)
{
- float const kEps = 1e-5;
size_t const trianglesCount = normals.size() / 3;
- float const side = isLeft ? kLeftSide : kRightSide;
for (size_t j = 0; j < trianglesCount; j++)
{
- glsl::vec3 const len1 = glsl::vec3(length.x, length.y, glsl::length(normals[3 * j]) < kEps ? kCenter : side);
- glsl::vec3 const len2 = glsl::vec3(length.x, length.y, glsl::length(normals[3 * j + 1]) < kEps ? kCenter : side);
- glsl::vec3 const len3 = glsl::vec3(length.x, length.y, glsl::length(normals[3 * j + 2]) < kEps ? kCenter : side);
+ glsl::vec3 const len1 = glsl::vec3(length.x, length.y, SideByNormal(normals[3 * j], isLeft));
+ glsl::vec3 const len2 = glsl::vec3(length.x, length.y, SideByNormal(normals[3 * j + 1], isLeft));
+ glsl::vec3 const len3 = glsl::vec3(length.x, length.y, SideByNormal(normals[3 * j + 2], isLeft));
joinsGeometry.push_back(RouteShape::RV(pivot, normals[3 * j], len1, color));
joinsGeometry.push_back(RouteShape::RV(pivot, normals[3 * j + 1], len2, color));
@@ -175,15 +182,23 @@ void RouteShape::PrepareGeometry(std::vector<m2::PointD> const & path, m2::Point
float const projRightStart = -segments[i].m_rightWidthScalar[StartPoint].y;
float const projRightEnd = segments[i].m_rightWidthScalar[EndPoint].y;
- geometry.push_back(RV(startPivot, glsl::vec2(0, 0), glsl::vec3(startLength, 0, kCenter), segments[i].m_color));
- geometry.push_back(RV(startPivot, leftNormalStart, glsl::vec3(startLength, projLeftStart, kLeftSide), segments[i].m_color));
- geometry.push_back(RV(endPivot, glsl::vec2(0, 0), glsl::vec3(length, 0, kCenter), segments[i].m_color));
- geometry.push_back(RV(endPivot, leftNormalEnd, glsl::vec3(length, projLeftEnd, kLeftSide), segments[i].m_color));
-
- geometry.push_back(RV(startPivot, rightNormalStart, glsl::vec3(startLength, projRightStart, kRightSide), segments[i].m_color));
- geometry.push_back(RV(startPivot, glsl::vec2(0, 0), glsl::vec3(startLength, 0, kCenter), segments[i].m_color));
- geometry.push_back(RV(endPivot, rightNormalEnd, glsl::vec3(length, projRightEnd, kRightSide), segments[i].m_color));
- geometry.push_back(RV(endPivot, glsl::vec2(0, 0), glsl::vec3(length, 0, kCenter), segments[i].m_color));
+ geometry.push_back(RV(startPivot, glsl::vec2(0, 0),
+ glsl::vec3(startLength, 0, kCenter), segments[i].m_color));
+ geometry.push_back(RV(startPivot, leftNormalStart,
+ glsl::vec3(startLength, projLeftStart, kLeftSide), segments[i].m_color));
+ geometry.push_back(RV(endPivot, glsl::vec2(0, 0),
+ glsl::vec3(length, 0, kCenter), segments[i].m_color));
+ geometry.push_back(RV(endPivot, leftNormalEnd,
+ glsl::vec3(length, projLeftEnd, kLeftSide), segments[i].m_color));
+
+ geometry.push_back(RV(startPivot, rightNormalStart,
+ glsl::vec3(startLength, projRightStart, kRightSide), segments[i].m_color));
+ geometry.push_back(RV(startPivot, glsl::vec2(0, 0),
+ glsl::vec3(startLength, 0, kCenter), segments[i].m_color));
+ geometry.push_back(RV(endPivot, rightNormalEnd,
+ glsl::vec3(length, projRightEnd, kRightSide), segments[i].m_color));
+ geometry.push_back(RV(endPivot, glsl::vec2(0, 0),
+ glsl::vec3(length, 0, kCenter), segments[i].m_color));
// Generate joins.
if (segments[i].m_generateJoin && i < static_cast<int>(segments.size()) - 1)
@@ -352,45 +367,6 @@ void RouteShape::PrepareArrowGeometry(std::vector<m2::PointD> const & path, m2::
}
}
-void RouteShape::CacheRouteSign(ref_ptr<dp::TextureManager> mng, RouteSignData & routeSignData)
-{
- dp::TextureManager::SymbolRegion symbol;
- mng->GetSymbolRegion(routeSignData.m_isStart ? "route_from" : "route_to", symbol);
-
- m2::RectF const & texRect = symbol.GetTexRect();
- m2::PointF halfSize = symbol.GetPixelSize() * 0.5f;
-
- glsl::vec4 const pivot = glsl::vec4(0.0f /* x */, 0.0f /* y */, 0.0f /* depth */, 0.0f /* pivot z */);
- gpu::SolidTexturingVertex data[4]=
- {
- { pivot, glsl::vec2(-halfSize.x, halfSize.y), glsl::ToVec2(texRect.LeftTop()) },
- { pivot, glsl::vec2(-halfSize.x, -halfSize.y), glsl::ToVec2(texRect.LeftBottom()) },
- { pivot, glsl::vec2( halfSize.x, halfSize.y), glsl::ToVec2(texRect.RightTop()) },
- { pivot, glsl::vec2( halfSize.x, -halfSize.y), glsl::ToVec2(texRect.RightBottom()) }
- };
-
- dp::GLState state(gpu::TEXTURING_PROGRAM, dp::GLState::OverlayLayer);
- if (!routeSignData.m_isStart)
- state.SetProgram3dIndex(gpu::TEXTURING_BILLBOARD_PROGRAM);
- state.SetColorTexture(symbol.GetTexture());
-
- {
- dp::Batcher batcher(dp::Batcher::IndexPerQuad, dp::Batcher::VertexPerQuad);
- dp::SessionGuard guard(batcher, [&routeSignData](dp::GLState const & state, drape_ptr<dp::RenderBucket> && b)
- {
- routeSignData.m_sign.m_buckets.push_back(move(b));
- routeSignData.m_sign.m_state = state;
- });
-
- dp::AttributeProvider provider(1 /* stream count */, dp::Batcher::VertexPerQuad);
- provider.InitStream(0 /* stream index */, gpu::SolidTexturingVertex::GetBindingInfo(), make_ref(data));
-
- dp::IndicesRange indices = batcher.InsertTriangleStrip(state, make_ref(&provider), nullptr);
- UNUSED_VALUE(indices);
- ASSERT(indices.IsValid(), ());
- }
-}
-
void RouteShape::CacheRouteArrows(ref_ptr<dp::TextureManager> mng, m2::PolylineD const & polyline,
std::vector<ArrowBorders> const & borders,
RouteArrowsData & routeArrowsData)
@@ -416,14 +392,14 @@ void RouteShape::CacheRouteArrows(ref_ptr<dp::TextureManager> mng, m2::PolylineD
BatchGeometry(state, make_ref(geometry.data()), static_cast<uint32_t>(geometry.size()),
make_ref(joinsGeometry.data()), static_cast<uint32_t>(joinsGeometry.size()),
- AV::GetBindingInfo(), routeArrowsData.m_arrows);
+ AV::GetBindingInfo(), routeArrowsData.m_renderProperty);
}
void RouteShape::CacheRoute(ref_ptr<dp::TextureManager> textures, RouteData & routeData)
{
std::vector<glsl::vec4> segmentsColors;
- segmentsColors.reserve(routeData.m_traffic.size());
- for (auto speedGroup : routeData.m_traffic)
+ segmentsColors.reserve(routeData.m_segment->m_traffic.size());
+ for (auto speedGroup : routeData.m_segment->m_traffic)
{
speedGroup = TrafficGenerator::CheckColorsSimplification(speedGroup);
auto const colorConstant = TrafficGenerator::GetColorBySpeedGroup(speedGroup, true /* route */);
@@ -436,16 +412,17 @@ void RouteShape::CacheRoute(ref_ptr<dp::TextureManager> textures, RouteData & ro
TGeometryBuffer geometry;
TGeometryBuffer joinsGeometry;
- PrepareGeometry(routeData.m_sourcePolyline.GetPoints(), routeData.m_pivot, segmentsColors,
+ PrepareGeometry(routeData.m_segment->m_polyline.GetPoints(), routeData.m_pivot, segmentsColors,
geometry, joinsGeometry, routeData.m_length);
- dp::GLState state =
- dp::GLState(routeData.m_pattern.m_isDashed ? gpu::ROUTE_DASH_PROGRAM : gpu::ROUTE_PROGRAM,
- dp::GLState::GeometryLayer);
+ dp::GLState state = dp::GLState(routeData.m_segment->m_pattern.m_isDashed ?
+ gpu::ROUTE_DASH_PROGRAM : gpu::ROUTE_PROGRAM,
+ dp::GLState::GeometryLayer);
state.SetColorTexture(textures->GetSymbolsTexture());
+
BatchGeometry(state, make_ref(geometry.data()), static_cast<uint32_t>(geometry.size()),
make_ref(joinsGeometry.data()), static_cast<uint32_t>(joinsGeometry.size()),
- RV::GetBindingInfo(), routeData.m_route);
+ RV::GetBindingInfo(), routeData.m_renderProperty);
}
void RouteShape::BatchGeometry(dp::GLState const & state, ref_ptr<void> geometry, uint32_t geomSize,
@@ -453,29 +430,29 @@ void RouteShape::BatchGeometry(dp::GLState const & state, ref_ptr<void> geometry
dp::BindingInfo const & bindingInfo, RouteRenderProperty & property)
{
size_t const verticesCount = geomSize + joinsGeomSize;
- if (verticesCount != 0)
+ if (verticesCount == 0)
+ return;
+
+ uint32_t const kBatchSize = 5000;
+ dp::Batcher batcher(kBatchSize, kBatchSize);
+ dp::SessionGuard guard(batcher, [&property](dp::GLState const & state, drape_ptr<dp::RenderBucket> && b)
{
- uint32_t const kBatchSize = 5000;
- dp::Batcher batcher(kBatchSize, kBatchSize);
- dp::SessionGuard guard(batcher, [&property](dp::GLState const & state, drape_ptr<dp::RenderBucket> && b)
- {
- property.m_buckets.push_back(move(b));
- property.m_state = state;
- });
+ property.m_buckets.push_back(move(b));
+ property.m_state = state;
+ });
- if (geomSize != 0)
- {
- dp::AttributeProvider provider(1 /* stream count */, geomSize);
- provider.InitStream(0 /* stream index */, bindingInfo, geometry);
- batcher.InsertListOfStrip(state, make_ref(&provider), 4);
- }
+ if (geomSize != 0)
+ {
+ dp::AttributeProvider provider(1 /* stream count */, geomSize);
+ provider.InitStream(0 /* stream index */, bindingInfo, geometry);
+ batcher.InsertListOfStrip(state, make_ref(&provider), 4);
+ }
- if (joinsGeomSize != 0)
- {
- dp::AttributeProvider joinsProvider(1 /* stream count */, joinsGeomSize);
- joinsProvider.InitStream(0 /* stream index */, bindingInfo, joinsGeometry);
- batcher.InsertTriangleList(state, make_ref(&joinsProvider));
- }
+ if (joinsGeomSize != 0)
+ {
+ dp::AttributeProvider joinsProvider(1 /* stream count */, joinsGeomSize);
+ joinsProvider.InitStream(0 /* stream index */, bindingInfo, joinsGeometry);
+ batcher.InsertTriangleList(state, make_ref(&joinsProvider));
}
}
} // namespace df
diff --git a/drape_frontend/route_shape.hpp b/drape_frontend/route_shape.hpp
index bab193800d..8d2acf7bf5 100644
--- a/drape_frontend/route_shape.hpp
+++ b/drape_frontend/route_shape.hpp
@@ -33,6 +33,14 @@ float const kArrowTailFactor = static_cast<float>(2.0 * kArrowTailTextureWidth /
double const kArrowHeightFactor = kArrowTextureHeight / kArrowBodyHeight;
double const kArrowAspect = kArrowTextureWidth / kArrowTextureHeight;
+enum class RouteType : uint8_t
+{
+ Car,
+ Pedestrian,
+ Bicycle,
+ Taxi
+};
+
struct RoutePattern
{
bool m_isDashed = false;
@@ -48,6 +56,24 @@ struct RoutePattern
{}
};
+struct RouteSegment
+{
+ df::RouteType m_routeType;
+ m2::PolylineD m_polyline;
+ df::ColorConstant m_color;
+ std::vector<double> m_turns;
+ std::vector<traffic::SpeedGroup> m_traffic;
+ df::RoutePattern m_pattern;
+
+ RouteSegment() = default;
+ RouteSegment(m2::PolylineD const & polyline, df::ColorConstant color,
+ std::vector<double> const & turns,
+ std::vector<traffic::SpeedGroup> const & traffic,
+ df::RoutePattern pattern = df::RoutePattern())
+ : m_polyline(polyline), m_color(color), m_turns(turns), m_traffic(traffic), m_pattern(pattern)
+ {}
+};
+
struct RouteRenderProperty
{
dp::GLState m_state;
@@ -55,41 +81,27 @@ struct RouteRenderProperty
RouteRenderProperty() : m_state(0, dp::GLState::GeometryLayer) {}
};
-struct ArrowBorders
+struct BaseRouteData
{
- double m_startDistance = 0;
- double m_endDistance = 0;
- int m_groupIndex = 0;
+ dp::DrapeID m_segmentId = 0;
+ m2::PointD m_pivot = m2::PointD(0.0, 0.0);
+ int m_recacheId = -1;
+ RouteRenderProperty m_renderProperty;
};
-struct RouteData
+struct RouteData : public BaseRouteData
{
- int m_routeIndex;
- m2::PolylineD m_sourcePolyline;
- std::vector<double> m_sourceTurns;
- m2::PointD m_pivot;
- df::ColorConstant m_color;
- std::vector<traffic::SpeedGroup> m_traffic;
- double m_length;
- RouteRenderProperty m_route;
- RoutePattern m_pattern;
- int m_recacheId;
+ drape_ptr<RouteSegment> m_segment;
+ double m_length = 0.0;
};
-struct RouteSignData
-{
- RouteRenderProperty m_sign;
- bool m_isStart;
- bool m_isValid;
- m2::PointD m_position;
- int m_recacheId;
-};
+struct RouteArrowsData : public BaseRouteData {};
-struct RouteArrowsData
+struct ArrowBorders
{
- RouteRenderProperty m_arrows;
- m2::PointD m_pivot;
- int m_recacheId;
+ double m_startDistance = 0.0;
+ double m_endDistance = 0.0;
+ int m_groupIndex = 0;
};
class RouteShape
@@ -101,7 +113,7 @@ public:
using TArrowGeometryBuffer = buffer_vector<AV, 128>;
static void CacheRoute(ref_ptr<dp::TextureManager> textures, RouteData & routeData);
- static void CacheRouteSign(ref_ptr<dp::TextureManager> mng, RouteSignData & routeSignData);
+
static void CacheRouteArrows(ref_ptr<dp::TextureManager> mng, m2::PolylineD const & polyline,
std::vector<ArrowBorders> const & borders,
RouteArrowsData & routeArrowsData);
diff --git a/iphone/Maps/Core/Routing/MWMRouter.mm b/iphone/Maps/Core/Routing/MWMRouter.mm
index d7abb0aa47..b459171276 100644
--- a/iphone/Maps/Core/Routing/MWMRouter.mm
+++ b/iphone/Maps/Core/Routing/MWMRouter.mm
@@ -202,8 +202,8 @@ bool isMarkerPoint(MWMRoutePoint * point) { return point.isValid && !point.isMyP
self.type =
routerType(GetFramework().GetRoutingManager().GetBestRouter(startPoint, finishPoint));
f.GetRoutingManager().BuildRoute(startPoint, finishPoint, isP2P, 0 /* timeoutSec */);
- f.GetRoutingManager().SetRouteStartPoint(startPoint, isMarkerPoint(self.startPoint));
- f.GetRoutingManager().SetRouteFinishPoint(finishPoint, isMarkerPoint(self.finishPoint));
+ f.GetRoutingManager().SetRouteStartPoint(f.GetBookmarkManager(), startPoint, isMarkerPoint(self.startPoint));
+ f.GetRoutingManager().SetRouteFinishPoint(f.GetBookmarkManager(), finishPoint, isMarkerPoint(self.finishPoint));
[mapViewControlsManager onRouteRebuild];
}
diff --git a/map/place_page_info.cpp b/map/place_page_info.cpp
index 4eb6ec48c1..b756123a75 100644
--- a/map/place_page_info.cpp
+++ b/map/place_page_info.cpp
@@ -28,6 +28,12 @@ bool Info::IsNotEditableSponsored() const
return m_sponsoredType != SponsoredType::None && m_sponsoredType != SponsoredType::Opentable;
}
+bool Info::IsRoutePoint() const
+{
+ //TODO(@darina) Implement checker
+ return m_bac.IsValid() && m_bookmarkCategoryName == "TMP_Routing_Points";
+}
+
bool Info::ShouldShowAddPlace() const
{
auto const isPointOrBuilding = IsPointType() || IsBuilding();
diff --git a/map/place_page_info.hpp b/map/place_page_info.hpp
index 40f9d87dec..ddc54c5994 100644
--- a/map/place_page_info.hpp
+++ b/map/place_page_info.hpp
@@ -53,6 +53,7 @@ public:
bool IsMyPosition() const;
bool IsSponsored() const;
bool IsNotEditableSponsored() const;
+ bool IsRoutePoint() const;
bool ShouldShowAddPlace() const;
bool ShouldShowAddBusiness() const;
diff --git a/map/routing_manager.cpp b/map/routing_manager.cpp
index 3ce9ad5e9b..6ae6c26102 100644
--- a/map/routing_manager.cpp
+++ b/map/routing_manager.cpp
@@ -184,8 +184,9 @@ void RoutingManager::SetRouterImpl(routing::RouterType type)
void RoutingManager::RemoveRoute(bool deactivateFollowing)
{
+ // TODO(@rokuz) use correct DrapeID
if (m_drapeEngine != nullptr)
- m_drapeEngine->RemoveRoute(deactivateFollowing);
+ m_drapeEngine->RemoveRouteSegment(dp::DrapeID(), deactivateFollowing);
}
void RoutingManager::InsertRoute(routing::Route const & route)
@@ -199,27 +200,38 @@ void RoutingManager::InsertRoute(routing::Route const & route)
return;
}
- std::vector<double> turns;
- if (m_currentRouterType == RouterType::Vehicle || m_currentRouterType == RouterType::Bicycle ||
- m_currentRouterType == RouterType::Taxi)
+ auto segment = make_unique_dp<df::RouteSegment>();
+ segment->m_polyline = route.GetPoly();
+ switch (m_currentRouterType)
{
- route.GetTurnsDistances(turns);
- }
-
- df::ColorConstant routeColor = df::kRouteColor;
- df::RoutePattern pattern;
- if (m_currentRouterType == RouterType::Pedestrian)
- {
- routeColor = df::kRoutePedestrian;
- pattern = df::RoutePattern(4.0, 2.0);
- }
- else if (m_currentRouterType == RouterType::Bicycle)
- {
- routeColor = df::kRouteBicycle;
- pattern = df::RoutePattern(8.0, 2.0);
+ case RouterType::Vehicle:
+ segment->m_routeType = df::RouteType::Car;
+ segment->m_color = df::kRouteColor;
+ segment->m_traffic = route.GetTraffic();
+ route.GetTurnsDistances(segment->m_turns);
+ break;
+ case RouterType::Pedestrian:
+ segment->m_routeType = df::RouteType::Pedestrian;
+ segment->m_color = df::kRoutePedestrian;
+ segment->m_pattern = df::RoutePattern(4.0, 2.0);
+ break;
+ case RouterType::Bicycle:
+ segment->m_routeType = df::RouteType::Bicycle;
+ segment->m_color = df::kRouteBicycle;
+ segment->m_pattern = df::RoutePattern(8.0, 2.0);
+ route.GetTurnsDistances(segment->m_turns);
+ break;
+ case RouterType::Taxi:
+ segment->m_routeType = df::RouteType::Taxi;
+ segment->m_color = df::kRouteColor;
+ segment->m_traffic = route.GetTraffic();
+ route.GetTurnsDistances(segment->m_turns);
+ break;
+ default: ASSERT(false, ("Unknown router type"));
}
- m_drapeEngine->AddRoute(route.GetPoly(), turns, routeColor, route.GetTraffic(), pattern);
+ dp::DrapeID const segmentId = m_drapeEngine->AddRouteSegment(std::move(segment));
+ // TODO (@rokuz) Save and use segment id
}
void RoutingManager::FollowRoute()
@@ -230,7 +242,8 @@ void RoutingManager::FollowRoute()
return;
m_delegate.OnRouteFollow(m_currentRouterType);
- m_drapeEngine->SetRoutePoint(m2::PointD(), true /* isStart */, false /* isValid */);
+
+ // TODO(@darina) Hide start point user mark
}
void RoutingManager::CloseRouting()
@@ -241,6 +254,8 @@ void RoutingManager::CloseRouting()
}
m_routingSession.Reset();
RemoveRoute(true /* deactivateFollowing */);
+
+ //TODO (@darina) Remove route points
}
void RoutingManager::SetLastUsedRouter(RouterType type)
@@ -248,16 +263,71 @@ void RoutingManager::SetLastUsedRouter(RouterType type)
settings::Set(kRouterTypeKey, routing::ToString(type));
}
-void RoutingManager::SetRouteStartPoint(m2::PointD const & pt, bool isValid)
+// TODO(@darina) Remove me
+// TEMPORARY {
+void TempAddBookmarkAsRoutePoint(BookmarkManager & bm, std::string const & name,
+ std::string const & bookmarkSymbol,
+ m2::PointD const & pt, bool isValid)
{
- if (m_drapeEngine != nullptr)
- m_drapeEngine->SetRoutePoint(pt, true /* isStart */, isValid);
+ std::string categoryName = "TMP_Routing_Points";
+ int categoryIndex = -1;
+ for (size_t i = 0; i < bm.GetBmCategoriesCount(); ++i)
+ {
+ if (bm.GetBmCategory(i)->GetName() == categoryName)
+ {
+ categoryIndex = static_cast<int>(i);
+ break;
+ }
+ }
+ if (categoryIndex == -1)
+ categoryIndex = bm.CreateBmCategory(categoryName);
+
+ if (!isValid)
+ {
+ BookmarkCategory * cat = bm.GetBmCategory(categoryIndex);
+ BookmarkCategory::Guard guard(*cat);
+ int indexToDelete = -1;
+ for (size_t i = 0; i < guard.m_controller.GetUserMarkCount(); ++i)
+ {
+ Bookmark const * bookmark = static_cast<Bookmark const *>(guard.m_controller.GetUserMark(i));
+ if (bookmark->GetName() == name)
+ {
+ indexToDelete = i;
+ break;
+ }
+ }
+ if (indexToDelete >= 0)
+ guard.m_controller.DeleteUserMark(indexToDelete);
+ }
+ else
+ {
+ BookmarkData dat(name, bookmarkSymbol);
+ bm.AddBookmark(categoryIndex, pt, dat);
+ }
+
+ {
+ BookmarkCategory * cat = bm.GetBmCategory(categoryIndex);
+ cat->SaveToKMLFile();
+ }
}
+// } TEMPORARY
-void RoutingManager::SetRouteFinishPoint(m2::PointD const & pt, bool isValid)
+void RoutingManager::SetRouteStartPoint(BookmarkManager & bm, m2::PointD const & pt, bool isValid)
{
- if (m_drapeEngine != nullptr)
- m_drapeEngine->SetRoutePoint(pt, false /* isStart */, isValid);
+ // TODO(@darina) Implement on new user marks
+ // TEMPORARY {
+ //TempAddBookmarkAsRoutePoint(bm, "Route start point", "placemark-blue",
+ // pt, isValid);
+ // } TEMPORARY
+}
+
+void RoutingManager::SetRouteFinishPoint(BookmarkManager & bm, m2::PointD const & pt, bool isValid)
+{
+ // TODO(@darina) Implement on new user marks
+ // TEMPORARY {
+ //TempAddBookmarkAsRoutePoint(bm, "Route end point", "placemark-green",
+ // pt, isValid);
+ // } TEMPORARY
}
void RoutingManager::GenerateTurnNotifications(std::vector<std::string> & turnNotifications)
diff --git a/map/routing_manager.hpp b/map/routing_manager.hpp
index 35e43a36fc..de9c76669d 100644
--- a/map/routing_manager.hpp
+++ b/map/routing_manager.hpp
@@ -1,10 +1,15 @@
-#include "drape/pointers.hpp"
+#pragma once
+
+// TODO (@darina) TEMPORARY Remove me
+#include "map/bookmark_manager.hpp"
#include "routing/route.hpp"
#include "routing/routing_session.hpp"
#include "storage/index.hpp"
+#include "drape/pointers.hpp"
+
#include "tracking/reporter.hpp"
#include "base/thread_checker.hpp"
@@ -154,8 +159,9 @@ public:
/// GenerateTurnNotifications shall be called by the client when a new position is available.
void GenerateTurnNotifications(std::vector<std::string> & turnNotifications);
- void SetRouteStartPoint(m2::PointD const & pt, bool isValid);
- void SetRouteFinishPoint(m2::PointD const & pt, bool isValid);
+ // TODO (@darina) Change interface to add/remove route point
+ void SetRouteStartPoint(BookmarkManager & bm, m2::PointD const & pt, bool isValid);
+ void SetRouteFinishPoint(BookmarkManager & bm, m2::PointD const & pt, bool isValid);
void SetRouterImpl(routing::RouterType type);
void RemoveRoute(bool deactivateFollowing);
@@ -171,7 +177,10 @@ public:
m_trackingReporter.SetAllowSendingPoints(isAllowed);
}
- void SetTurnNotificationsUnits(measurement_utils::Units const units) { m_routingSession.SetTurnNotificationsUnits(units); }
+ void SetTurnNotificationsUnits(measurement_utils::Units const units)
+ {
+ m_routingSession.SetTurnNotificationsUnits(units);
+ }
void SetDrapeEngine(ref_ptr<df::DrapeEngine> engine, bool is3dAllowed);
/// \returns true if altitude information along |m_route| is available and
/// false otherwise.
@@ -199,13 +208,13 @@ private:
void MatchLocationToRoute(location::GpsInfo & info,
location::RouteMatchingInfo & routeMatchingInfo) const;
-private:
RouteBuildingCallback m_routingCallback = nullptr;
Callbacks m_callbacks;
ref_ptr<df::DrapeEngine> m_drapeEngine = nullptr;
routing::RouterType m_currentRouterType = routing::RouterType::Count;
routing::RoutingSession m_routingSession;
- DECLARE_THREAD_CHECKER(m_threadChecker);
Delegate & m_delegate;
tracking::Reporter m_trackingReporter;
+
+ DECLARE_THREAD_CHECKER(m_threadChecker);
};