mirror of
https://codeberg.org/comaps/comaps
synced 2025-12-20 13:23:59 +00:00
Organic Maps sources as of 02.04.2025 (fad26bbf22ac3da75e01e62aa01e5c8e11861005)
To expand with full Organic Maps and Maps.ME commits history run: git remote add om-historic [om-historic.git repo url] git fetch --tags om-historic git replace squashed-history historic-commits
This commit is contained in:
264
drape_frontend/my_position.cpp
Normal file
264
drape_frontend/my_position.cpp
Normal file
@@ -0,0 +1,264 @@
|
||||
#include "drape_frontend/my_position.hpp"
|
||||
#include "drape_frontend/batcher_bucket.hpp"
|
||||
#include "drape_frontend/color_constants.hpp"
|
||||
#include "drape_frontend/map_shape.hpp"
|
||||
#include "drape_frontend/shape_view_params.hpp"
|
||||
#include "drape_frontend/tile_utils.hpp"
|
||||
|
||||
#include "shaders/programs.hpp"
|
||||
|
||||
#include "drape/constants.hpp"
|
||||
#include "drape/glsl_func.hpp"
|
||||
#include "drape/glsl_types.hpp"
|
||||
#include "drape/overlay_handle.hpp"
|
||||
#include "drape/render_bucket.hpp"
|
||||
|
||||
|
||||
namespace df
|
||||
{
|
||||
namespace mp
|
||||
{
|
||||
df::ColorConstant const kMyPositionAccuracyColor = "MyPositionAccuracy";
|
||||
|
||||
struct MarkerVertex
|
||||
{
|
||||
MarkerVertex() = default;
|
||||
MarkerVertex(glsl::vec2 const & normal, glsl::vec2 const & texCoord)
|
||||
: m_normal(normal)
|
||||
, m_texCoord(texCoord)
|
||||
{}
|
||||
|
||||
glsl::vec2 m_normal;
|
||||
glsl::vec2 m_texCoord;
|
||||
};
|
||||
|
||||
dp::BindingInfo GetMarkerBindingInfo()
|
||||
{
|
||||
dp::BindingInfo info(2);
|
||||
dp::BindingDecl & normal = info.GetBindingDecl(0);
|
||||
normal.m_attributeName = "a_normal";
|
||||
normal.m_componentCount = 2;
|
||||
normal.m_componentType = gl_const::GLFloatType;
|
||||
normal.m_offset = 0;
|
||||
normal.m_stride = sizeof(MarkerVertex);
|
||||
|
||||
dp::BindingDecl & texCoord = info.GetBindingDecl(1);
|
||||
texCoord.m_attributeName = "a_colorTexCoords";
|
||||
texCoord.m_componentCount = 2;
|
||||
texCoord.m_componentType = gl_const::GLFloatType;
|
||||
texCoord.m_offset = sizeof(glsl::vec2);
|
||||
texCoord.m_stride = sizeof(MarkerVertex);
|
||||
|
||||
return info;
|
||||
}
|
||||
} // namespace mp
|
||||
|
||||
MyPosition::MyPosition(ref_ptr<dp::GraphicsContext> context, ref_ptr<dp::TextureManager> mng)
|
||||
: m_position(m2::PointF::Zero())
|
||||
, m_azimuth(0.0f)
|
||||
, m_accuracy(0.0f)
|
||||
, m_showAzimuth(false)
|
||||
, m_isRoutingMode(false)
|
||||
{
|
||||
m_parts.resize(4);
|
||||
CacheAccuracySector(context, mng);
|
||||
CachePointPosition(context, mng);
|
||||
}
|
||||
|
||||
bool MyPosition::InitArrow(ref_ptr<dp::GraphicsContext> context, ref_ptr<dp::TextureManager> mng,
|
||||
Arrow3d::PreloadedData && preloadedData)
|
||||
{
|
||||
m_arrow3d = make_unique_dp<Arrow3d>(context, mng, std::move(preloadedData));
|
||||
return m_arrow3d->IsValid();
|
||||
}
|
||||
|
||||
void MyPosition::SetPosition(m2::PointF const & pt)
|
||||
{
|
||||
m_position = pt;
|
||||
}
|
||||
|
||||
void MyPosition::SetAzimuth(float azimut)
|
||||
{
|
||||
m_azimuth = azimut;
|
||||
}
|
||||
|
||||
void MyPosition::SetIsValidAzimuth(bool isValid)
|
||||
{
|
||||
m_showAzimuth = isValid;
|
||||
}
|
||||
|
||||
void MyPosition::SetAccuracy(float accuracy)
|
||||
{
|
||||
m_accuracy = accuracy;
|
||||
}
|
||||
|
||||
void MyPosition::SetRoutingMode(bool routingMode)
|
||||
{
|
||||
m_isRoutingMode = routingMode;
|
||||
}
|
||||
|
||||
void MyPosition::SetPositionObsolete(bool obsolete)
|
||||
{
|
||||
CHECK(m_arrow3d != nullptr, ());
|
||||
m_arrow3d->SetPositionObsolete(obsolete);
|
||||
}
|
||||
|
||||
void MyPosition::RenderAccuracy(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng,
|
||||
ScreenBase const & screen, int zoomLevel, FrameValues const & frameValues)
|
||||
{
|
||||
m2::PointD accuracyPoint(m_position.x + m_accuracy, m_position.y);
|
||||
auto const pixelAccuracy =
|
||||
static_cast<float>((screen.GtoP(accuracyPoint) - screen.GtoP(m2::PointD(m_position))).Length());
|
||||
|
||||
gpu::ShapesProgramParams params;
|
||||
frameValues.SetTo(params);
|
||||
TileKey const key = GetTileKeyByPoint(m2::PointD(m_position), ClipTileZoomByMaxDataZoom(zoomLevel));
|
||||
math::Matrix<float, 4, 4> mv = key.GetTileBasedModelView(screen);
|
||||
params.m_modelView = glsl::make_mat4(mv.m_data);
|
||||
|
||||
auto const pos = static_cast<m2::PointF>(
|
||||
MapShape::ConvertToLocal(m2::PointD(m_position), key.GetGlobalRect().Center(), kShapeCoordScalar));
|
||||
params.m_position = glsl::vec3(pos.x, pos.y, 0.0f);
|
||||
params.m_accuracy = pixelAccuracy;
|
||||
RenderPart(context, mng, params, MyPositionAccuracy);
|
||||
}
|
||||
|
||||
void MyPosition::RenderMyPosition(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng,
|
||||
ScreenBase const & screen, int zoomLevel, FrameValues const & frameValues)
|
||||
{
|
||||
if (m_showAzimuth)
|
||||
{
|
||||
CHECK(m_arrow3d != nullptr, ());
|
||||
m_arrow3d->SetPosition(m2::PointD(m_position));
|
||||
m_arrow3d->SetAzimuth(m_azimuth);
|
||||
m_arrow3d->Render(context, mng, screen, m_isRoutingMode);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpu::ShapesProgramParams params;
|
||||
frameValues.SetTo(params);
|
||||
TileKey const key = GetTileKeyByPoint(m2::PointD(m_position), ClipTileZoomByMaxDataZoom(zoomLevel));
|
||||
math::Matrix<float, 4, 4> mv = key.GetTileBasedModelView(screen);
|
||||
params.m_modelView = glsl::make_mat4(mv.m_data);
|
||||
|
||||
auto const pos = static_cast<m2::PointF>(
|
||||
MapShape::ConvertToLocal(m2::PointD(m_position), key.GetGlobalRect().Center(), kShapeCoordScalar));
|
||||
params.m_position = glsl::vec3(pos.x, pos.y, dp::depth::kMyPositionMarkDepth);
|
||||
params.m_azimut = -(m_azimuth + static_cast<float>(screen.GetAngle()));
|
||||
RenderPart(context, mng, params, MyPositionPoint);
|
||||
}
|
||||
}
|
||||
|
||||
void MyPosition::CacheAccuracySector(ref_ptr<dp::GraphicsContext> context,
|
||||
ref_ptr<dp::TextureManager> mng)
|
||||
{
|
||||
size_t constexpr kTriangleCount = 40;
|
||||
size_t constexpr kVertexCount = 3 * kTriangleCount;
|
||||
auto const etalonSector = static_cast<float>(2.0 * math::pi / kTriangleCount);
|
||||
|
||||
dp::TextureManager::ColorRegion color;
|
||||
mng->GetColorRegion(df::GetColorConstant(mp::kMyPositionAccuracyColor), color);
|
||||
glsl::vec2 colorCoord = glsl::ToVec2(color.GetTexRect().Center());
|
||||
|
||||
buffer_vector<mp::MarkerVertex, kTriangleCount> buffer;
|
||||
glsl::vec2 startNormal(0.0f, 1.0f);
|
||||
|
||||
for (size_t i = 0; i < kTriangleCount + 1; ++i)
|
||||
{
|
||||
glsl::vec2 normal = glsl::rotate(startNormal, i * etalonSector);
|
||||
glsl::vec2 nextNormal = glsl::rotate(startNormal, (i + 1) * etalonSector);
|
||||
|
||||
buffer.emplace_back(glsl::vec2(0.0f, 0.0f), colorCoord);
|
||||
buffer.emplace_back(normal, colorCoord);
|
||||
buffer.emplace_back(nextNormal, colorCoord);
|
||||
}
|
||||
|
||||
auto state = CreateRenderState(gpu::Program::Accuracy, DepthLayer::OverlayLayer);
|
||||
state.SetDepthTestEnabled(false);
|
||||
state.SetColorTexture(color.GetTexture());
|
||||
|
||||
{
|
||||
dp::Batcher batcher(kTriangleCount * dp::Batcher::IndexPerTriangle, kVertexCount);
|
||||
batcher.SetBatcherHash(static_cast<uint64_t>(BatcherBucket::Default));
|
||||
dp::SessionGuard guard(context, batcher,
|
||||
[this](dp::RenderState const & state, drape_ptr<dp::RenderBucket> && b)
|
||||
{
|
||||
drape_ptr<dp::RenderBucket> bucket = std::move(b);
|
||||
ASSERT(bucket->GetOverlayHandlesCount() == 0, ());
|
||||
|
||||
m_nodes.emplace_back(state, bucket->MoveBuffer());
|
||||
m_parts[MyPositionAccuracy].second = m_nodes.size() - 1;
|
||||
});
|
||||
|
||||
dp::AttributeProvider provider(1 /* stream count */, kVertexCount);
|
||||
provider.InitStream(0 /* stream index */, mp::GetMarkerBindingInfo(), make_ref(buffer.data()));
|
||||
|
||||
m_parts[MyPositionAccuracy].first = batcher.InsertTriangleList(context, state,
|
||||
make_ref(&provider), nullptr);
|
||||
ASSERT(m_parts[MyPositionAccuracy].first.IsValid(), ());
|
||||
}
|
||||
}
|
||||
|
||||
void MyPosition::CacheSymbol(ref_ptr<dp::GraphicsContext> context,
|
||||
dp::TextureManager::SymbolRegion const & symbol,
|
||||
dp::RenderState const & state, dp::Batcher & batcher,
|
||||
EMyPositionPart part)
|
||||
{
|
||||
m2::RectF const & texRect = symbol.GetTexRect();
|
||||
m2::PointF const halfSize = symbol.GetPixelSize() * 0.5f;
|
||||
|
||||
mp::MarkerVertex data[4] =
|
||||
{
|
||||
{ glsl::vec2(-halfSize.x, halfSize.y), glsl::ToVec2(texRect.LeftTop()) },
|
||||
{ glsl::vec2(-halfSize.x, -halfSize.y), glsl::ToVec2(texRect.LeftBottom()) },
|
||||
{ glsl::vec2( halfSize.x, halfSize.y), glsl::ToVec2(texRect.RightTop()) },
|
||||
{ glsl::vec2( halfSize.x, -halfSize.y), glsl::ToVec2(texRect.RightBottom())}
|
||||
};
|
||||
|
||||
dp::AttributeProvider provider(1 /* streamCount */, dp::Batcher::VertexPerQuad);
|
||||
provider.InitStream(0 /* streamIndex */, mp::GetMarkerBindingInfo(), make_ref(data));
|
||||
m_parts[part].first = batcher.InsertTriangleStrip(context, state, make_ref(&provider), nullptr);
|
||||
ASSERT(m_parts[part].first.IsValid(), ());
|
||||
}
|
||||
|
||||
void MyPosition::CachePointPosition(ref_ptr<dp::GraphicsContext> context, ref_ptr<dp::TextureManager> mng)
|
||||
{
|
||||
int const kSymbolsCount = 1;
|
||||
dp::TextureManager::SymbolRegion pointSymbol;
|
||||
mng->GetSymbolRegion("current-position", pointSymbol);
|
||||
|
||||
auto state = CreateRenderState(gpu::Program::MyPosition, DepthLayer::OverlayLayer);
|
||||
state.SetDepthTestEnabled(false);
|
||||
state.SetColorTexture(pointSymbol.GetTexture());
|
||||
state.SetTextureIndex(pointSymbol.GetTextureIndex());
|
||||
|
||||
dp::TextureManager::SymbolRegion * symbols[kSymbolsCount] = { &pointSymbol };
|
||||
EMyPositionPart partIndices[kSymbolsCount] = { MyPositionPoint };
|
||||
{
|
||||
dp::Batcher batcher(kSymbolsCount * dp::Batcher::IndexPerQuad, kSymbolsCount * dp::Batcher::VertexPerQuad);
|
||||
batcher.SetBatcherHash(static_cast<uint64_t>(BatcherBucket::Default));
|
||||
dp::SessionGuard guard(context, batcher,
|
||||
[this](dp::RenderState const & state, drape_ptr<dp::RenderBucket> && b)
|
||||
{
|
||||
drape_ptr<dp::RenderBucket> bucket = std::move(b);
|
||||
ASSERT(bucket->GetOverlayHandlesCount() == 0, ());
|
||||
|
||||
m_nodes.emplace_back(state, bucket->MoveBuffer());
|
||||
});
|
||||
|
||||
auto const partIndex = m_nodes.size();
|
||||
for (int i = 0; i < kSymbolsCount; i++)
|
||||
{
|
||||
m_parts[partIndices[i]].second = partIndex;
|
||||
CacheSymbol(context, *symbols[i], state, batcher, partIndices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MyPosition::RenderPart(ref_ptr<dp::GraphicsContext> context, ref_ptr<gpu::ProgramManager> mng,
|
||||
gpu::ShapesProgramParams const & params, EMyPositionPart part)
|
||||
{
|
||||
TPart const & p = m_parts[part];
|
||||
m_nodes[p.second].Render(context, mng, params, p.first);
|
||||
}
|
||||
} // namespace df
|
||||
Reference in New Issue
Block a user