From 85a5f9996ee016fff815c0ed97ad014231fe588d Mon Sep 17 00:00:00 2001 From: Daria Volvenkova Date: Mon, 19 Jun 2017 09:37:54 +0300 Subject: [PATCH] Tile based user mark generation. --- drape_frontend/drape_frontend.pro | 4 + drape_frontend/user_mark_builder.cpp | 16 +++ drape_frontend/user_mark_builder.hpp | 20 ++++ drape_frontend/user_mark_generator.cpp | 155 +++++++++++++++++++++++++ drape_frontend/user_mark_generator.hpp | 111 ++++++++++++++++++ 5 files changed, 306 insertions(+) create mode 100644 drape_frontend/user_mark_builder.cpp create mode 100644 drape_frontend/user_mark_builder.hpp create mode 100644 drape_frontend/user_mark_generator.cpp create mode 100644 drape_frontend/user_mark_generator.hpp diff --git a/drape_frontend/drape_frontend.pro b/drape_frontend/drape_frontend.pro index f2ba02e446..6e488d2f8e 100755 --- a/drape_frontend/drape_frontend.pro +++ b/drape_frontend/drape_frontend.pro @@ -114,6 +114,8 @@ SOURCES += \ watch/geometry_processors.cpp \ watch/feature_processor.cpp \ watch/default_font.cpp \ + user_mark_builder.cpp \ + user_mark_generator.cpp HEADERS += \ animation/animation.hpp \ @@ -235,6 +237,8 @@ HEADERS += \ watch/brush_info.hpp \ watch/geometry_processors.hpp \ watch/feature_processor.hpp \ + user_mark_builder.hpp \ + user_mark_generator.hpp OTHER_FILES += \ shaders/area.vsh.glsl \ diff --git a/drape_frontend/user_mark_builder.cpp b/drape_frontend/user_mark_builder.cpp new file mode 100644 index 0000000000..ce52ec8c31 --- /dev/null +++ b/drape_frontend/user_mark_builder.cpp @@ -0,0 +1,16 @@ +#include "drape_frontend/user_mark_builder.hpp" + +namespace df +{ +UserMarkBuilder::UserMarkBuilder(TFlushFn const & flushFn) + : m_flushFn(flushFn) +{ + +} + +void UserMarkBuilder::BuildUserMarks(UserMarksRenderCollection const & marks, MarkIndexesCollection && indexes, + ref_ptr textures) +{ + +} +} // namespace df diff --git a/drape_frontend/user_mark_builder.hpp b/drape_frontend/user_mark_builder.hpp new file mode 100644 index 0000000000..51a950d6fb --- /dev/null +++ b/drape_frontend/user_mark_builder.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "drape_frontend/user_mark_shapes.hpp" +#include "drape_frontend/user_mark_generator.hpp" + +namespace df +{ +class UserMarkBuilder +{ +public: + using TFlushFn = function; + + UserMarkBuilder(TFlushFn const & flushFn); + + void BuildUserMarks(MarkGroups const & marks, MarkIndexesGroups && indexes, + ref_ptr textures); +private: + TFlushFn m_flushFn; +}; +} diff --git a/drape_frontend/user_mark_generator.cpp b/drape_frontend/user_mark_generator.cpp new file mode 100644 index 0000000000..41088d9736 --- /dev/null +++ b/drape_frontend/user_mark_generator.cpp @@ -0,0 +1,155 @@ +#include "drape_frontend/user_mark_generator.hpp" + +namespace df +{ +UserMarkGenerator::UserMarkGenerator() +{ +} + +void UserMarkGenerator::SetUserMarks(uint32_t groupId, drape_ptr && marks) +{ + m_marks.insert(make_pair(groupId, std::move(marks))); + UpdateMarksIndex(groupId); +} + +void UserMarkGenerator::SetUserLines(uint32_t groupId, drape_ptr && lines) +{ + m_lines.insert(make_pair(groupId, std::move(lines))); + UpdateLinesIndex(groupId); +} + +void UserMarkGenerator::UpdateMarksIndex(uint32_t groupId) +{ + for (auto & tileGroups : m_marksIndex) + { + auto itGroupIndexes = tileGroups.second->find(groupId); + if (itGroupIndexes != tileGroups.second->end()) + itGroupIndexes->second->clear(); + } + + UserMarksRenderCollection & marks = *m_marks[groupId]; + for (size_t markIndex = 0; markIndex < marks.size(); ++markIndex) + { + for (size_t zoomLevel = 1; zoomLevel <= scales::GetUpperScale(); ++zoomLevel) + { + TileKey const tileKey = GetTileKeyByPoint(marks[markIndex].m_pivot, zoomLevel); + + ref_ptr tileGroups; + auto itTileGroups = m_marksIndex.find(tileKey); + if (itTileGroups == m_marksIndex.end()) + { + auto tileIndexesGroups = make_unique_dp(); + tileGroups = make_ref(tileIndexesGroups); + m_marksIndex.insert(make_pair(tileKey, std::move(tileIndexesGroups))); + } + else + { + tileGroups = make_ref(itTileGroups->second); + } + + ref_ptr groupIndexes; + auto itGroupIndexes = tileGroups->find(groupId); + if (itGroupIndexes == tileGroups->end()) + { + auto groupMarkIndexes = make_unique_dp(); + groupIndexes = make_ref(groupMarkIndexes); + tileGroups->insert(make_pair(groupId, std::move(groupMarkIndexes))); + } + else + { + groupIndexes = make_ref(itGroupIndexes->second); + } + + groupIndexes->push_back(static_cast(markIndex)); + } + } + + for (auto tileIt = m_marksIndex.begin(); tileIt != m_marksIndex.end();) + { + if (tileIt->second->empty()) + tileIt = m_marksIndex.erase(tileIt); + else + ++tileIt; + } +} + +void UserMarkGenerator::UpdateLinesIndex(uint32_t groupId) +{ + +} + +void UserMarkGenerator::SetGroupVisibility(GroupID groupId, bool isVisible) +{ + m_groupsVisibility[groupId] = isVisible; +} + +void UserMarkGenerator::GenerateUserMarksGeometry(TileKey const & tileKey, ref_ptr textures) +{ + MarksIndex::const_iterator itTile = m_marksIndex.find(tileKey); + if (itTile == m_marksIndex.end()) + return; + + MarkIndexesGroups & indexesGroups = *itTile->second; + for (auto & groupPair : indexesGroups) + { + GroupID groupId = groupPair.first; + MarkIndexesCollection & indexes = *groupPair.second; + + if (!m_groupsVisibility[groupId]) + continue; + + UserMarkBatcherKey batcherKey(tileKey, groupId); + m_batchersPool->ReserveBatcher(batcherKey); + ref_ptr batcher = m_batchersPool->GetBatcher(batcherKey); + + dp::TextureManager::SymbolRegion region; + + uint32_t const vertexCount = static_cast(it->second.size()) * dp::Batcher::VertexPerQuad; + uint32_t const indicesCount = static_cast(it->second.size()) * dp::Batcher::IndexPerQuad; + buffer_vector buffer; + buffer.reserve(vertexCount); + + for (auto const markIndex : indexes) + { + UserMarkRenderInfo const & renderInfo = m_marks[markIndex]; + if (!renderInfo.m_isVisible) + continue; + textures->GetSymbolRegion(renderInfo.m_symbolName, region); + m2::RectF const & texRect = region.GetTexRect(); + m2::PointF const pxSize = region.GetPixelSize(); + dp::Anchor const anchor = renderInfo.m_anchor; + m2::PointD const pt = MapShape::ConvertToLocal(renderInfo.m_pivot, tileKey.GetGlobalRect().Center(), kShapeCoordScalar); + glsl::vec3 const pos = glsl::vec3(glsl::ToVec2(pt), renderInfo.m_depth); + bool const runAnim = renderInfo.m_runCreationAnim; + + glsl::vec2 left, right, up, down; + AlignHorizontal(pxSize.x * 0.5f, anchor, left, right); + AlignVertical(pxSize.y * 0.5f, anchor, up, down); + + m2::PointD const pixelOffset = pointMark->GetPixelOffset(); + glsl::vec2 const offset(pixelOffset.x, pixelOffset.y); + + buffer.emplace_back(pos, left + down + offset, glsl::ToVec2(texRect.LeftTop()), runAnim); + buffer.emplace_back(pos, left + up + offset, glsl::ToVec2(texRect.LeftBottom()), runAnim); + buffer.emplace_back(pos, right + down + offset, glsl::ToVec2(texRect.RightTop()), runAnim); + buffer.emplace_back(pos, right + up + offset, glsl::ToVec2(texRect.RightBottom()), runAnim); + } + + dp::GLState state(gpu::BOOKMARK_PROGRAM, dp::GLState::UserMarkLayer); + state.SetProgram3dIndex(gpu::BOOKMARK_BILLBOARD_PROGRAM); + state.SetColorTexture(region.GetTexture()); + state.SetTextureFilter(gl_const::GLNearest); + + uint32_t const kMaxSize = 65000; + dp::Batcher batcher(min(indicesCount, kMaxSize), min(vertexCount, kMaxSize)); + dp::SessionGuard guard(batcher, [&key, &outShapes](dp::GLState const & state, + drape_ptr && b) + { + outShapes.emplace_back(UserMarkShape(state, move(b), key)); + }); + dp::AttributeProvider attribProvider(1, static_cast(buffer.size())); + attribProvider.InitStream(0, UPV::GetBinding(), make_ref(buffer.data())); + batcher.InsertListOfStrip(state, make_ref(&attribProvider), dp::Batcher::VertexPerQuad); + } +} +} // namespace df diff --git a/drape_frontend/user_mark_generator.hpp b/drape_frontend/user_mark_generator.hpp new file mode 100644 index 0000000000..6d6d628e8c --- /dev/null +++ b/drape_frontend/user_mark_generator.hpp @@ -0,0 +1,111 @@ +#pragma once + +#include "drape_frontend/batchers_pool.hpp" +#include "drape_frontend/tile_utils.hpp" +#include "drape_frontend/user_mark_shapes.hpp" + +#include "drape/drape_global.hpp" +#include "drape/pointers.hpp" + +#include "indexer/scales.hpp" + +#include +#include +#include +#include + +namespace df +{ +struct UserMarkRenderInfo +{ + m2::PointD m_pivot; + m2::PointD m_pixelOffset; + std::string m_symbolName; + dp::Anchor m_anchor; + float m_depth; + bool m_runCreationAnim; + bool m_isVisible; +}; + +struct LineLayer +{ + dp::Color m_color; + float m_width; + float m_depth; +}; + +struct UserLineRenderInfo +{ + std::vector m_layers; + std::vector m_points; +}; + +using UserMarksRenderCollection = std::vector; +using UserLinesRenderCollection = std::vector; + +using GroupID = uint32_t; + +using MarkGroups = std::map>; +using LineGroups = std::map>; + +using MarkIndexesCollection = std::vector; +using MarkIndexesGroups = std::map>; + +using MarksIndex = std::map>; + +class UserMarkGenerator +{ +public: + using TFlushFn = function; + + UserMarkGenerator(TFlushFn const & flushFn); + + void SetUserMarks(GroupID groupId, drape_ptr && marks); + void SetUserLines(GroupID groupId, drape_ptr && lines); + + void SetGroupVisibility(GroupID groupId, bool isVisible); + + void GenerateUserMarksGeometry(TileKey const & tileKey, ref_ptr textures); + +private: + TFlushFn m_flushFn; +private: + void UpdateMarksIndex(GroupID groupId); + void UpdateLinesIndex(GroupID groupId); + + struct UserMarkBatcherKey + { + UserMarkBatcherKey() = default; + UserMarkBatcherKey(TileKey const & tileKey, GroupID groupId) + : m_tileKey(tileKey) + , m_groupId(groupId) + {} + GroupID m_groupId; + TileKey m_tileKey; + }; + + struct UserMarkBatcherKeyComparator + { + bool operator() (UserMarkBatcherKey const & lhs, UserMarkBatcherKey const & rhs) const + { + if (lhs.m_groupId == rhs.m_groupId) + return lhs.m_tileKey.LessStrict(rhs.m_tileKey); + return lhs.m_groupId < rhs.m_groupId; + } + }; + + void FlushGeometry(UserMarkBatcherKey const & key, dp::GLState const & state, + drape_ptr && buffer); + + drape_ptr> m_batchersPool; + TFlushFn m_flushRenderDataFn; + + std::map m_groupsVisibility; + + MarkGroups m_marks; + LineGroups m_lines; + + MarksIndex m_marksIndex; +}; + +} // namespace df