#include "drape_frontend/arrow3d.hpp" #include "drape_frontend/color_constants.hpp" #include "drape_frontend/visual_params.hpp" #include "shaders/program_manager.hpp" #include "drape/texture_manager.hpp" #include "indexer/map_style_reader.hpp" #include "indexer/scales.hpp" #include "geometry/screenbase.hpp" namespace df { double constexpr kArrowSize = 12.0; double constexpr kArrow3dScaleMin = 1.0; double constexpr kArrow3dScaleMax = 2.2; int constexpr kArrow3dMinZoom = 16; float constexpr kOutlineScale = 1.2f; int constexpr kComponentsInVertex = 4; int constexpr kComponentsInNormal = 3; df::ColorConstant const kArrow3DShadowColor = "Arrow3DShadow"; df::ColorConstant const kArrow3DObsoleteColor = "Arrow3DObsolete"; df::ColorConstant const kArrow3DColor = "Arrow3D"; df::ColorConstant const kArrow3DOutlineColor = "Arrow3DOutline"; Arrow3d::Arrow3d() : m_arrowMesh(dp::MeshObject::DrawPrimitive::Triangles) , m_shadowMesh(dp::MeshObject::DrawPrimitive::Triangles) , m_state(CreateRenderState(gpu::Program::Arrow3d, DepthLayer::OverlayLayer)) { m_state.SetDepthTestEnabled(false); std::vector vertices = { 0.0f, 0.0f, -1.0f, 1.0f, -1.2f, -1.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 1.2f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, -0.5f, 0.0f, 1.0f, -1.2f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 1.2f, -1.0f, 0.0f, 1.0f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, 2.27f, 0.0f, 0.0f, 1.4f, -1.17f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, 1.0f, 0.0f, 2.0f, 0.0f, 1.0f, 1.4f, -1.17f, 0.0f, 0.0f, 1.2f, -1.0f, 0.0f, 1.0f, 0.0f, 2.27f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, 1.0f, -1.4f, -1.17f, 0.0f, 0.0f, 0.0f, 2.0f, 0.0f, 1.0f, -1.2f, -1.0f, 0.0f, 1.0f, -1.4f, -1.17f, 0.0f, 0.0f, 1.2f, -1.0f, 0.0f, 1.0f, 1.4f, -1.17f, 0.0f, 0.0f, 0.0f, -0.67f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 1.0f, 1.2f, -1.0f, 0.0f, 1.0f, 0.0f, -0.67f, 0.0f, 0.0f, -1.2f, -1.0f, 0.0f, 1.0f, 0.0f, -0.67f, 0.0f, 0.0f, -1.4f, -1.17f, 0.0f, 0.0f, 0.0f, -0.5f, 0.0f, 1.0f, 0.0f, -0.67f, 0.0f, 0.0f, -1.2f, -1.0f, 0.0f, 1.0f, }; std::vector normals = dp::MeshObject::GenerateNormalsForTriangles(vertices, kComponentsInVertex); auto constexpr kVerticesBufferInd = 0; auto copiedVertices = vertices; m_arrowMesh.SetBuffer(kVerticesBufferInd, std::move(copiedVertices), sizeof(float) * kComponentsInVertex); m_arrowMesh.SetAttribute("a_pos", kVerticesBufferInd, 0 /* offset */, kComponentsInVertex); auto constexpr kNormalsBufferInd = 1; m_arrowMesh.SetBuffer(kNormalsBufferInd, std::move(normals), sizeof(float) * kComponentsInNormal); m_arrowMesh.SetAttribute("a_normal", kNormalsBufferInd, 0 /* offset */, kComponentsInNormal); m_shadowMesh.SetBuffer(kVerticesBufferInd, std::move(vertices), sizeof(float) * kComponentsInVertex); m_shadowMesh.SetAttribute("a_pos", kVerticesBufferInd, 0 /* offset */, kComponentsInVertex); } void Arrow3d::SetPosition(const m2::PointD & position) { m_position = position; } void Arrow3d::SetAzimuth(double azimuth) { m_azimuth = azimuth; } void Arrow3d::SetTexture(ref_ptr texMng) { m_state.SetColorTexture(texMng->GetSymbolsTexture()); } void Arrow3d::SetPositionObsolete(bool obsolete) { m_obsoletePosition = obsolete; } void Arrow3d::Render(ref_ptr context, ref_ptr mng, ScreenBase const & screen, bool routingMode) { // Render shadow. if (screen.isPerspective()) { RenderArrow(context, mng, m_shadowMesh, screen, gpu::Program::Arrow3dShadow, df::GetColorConstant(df::kArrow3DShadowColor), 0.05f /* dz */, routingMode ? kOutlineScale : 1.0f /* scaleFactor */); } // Render outline. if (routingMode) { dp::Color const outlineColor = df::GetColorConstant(df::kArrow3DOutlineColor); RenderArrow(context, mng, m_shadowMesh, screen, gpu::Program::Arrow3dOutline, outlineColor, 0.0f /* dz */, kOutlineScale /* scaleFactor */); } // Render arrow. dp::Color const color = df::GetColorConstant(m_obsoletePosition ? df::kArrow3DObsoleteColor : df::kArrow3DColor); RenderArrow(context, mng, m_arrowMesh, screen, gpu::Program::Arrow3d, color, 0.0f /* dz */, 1.0f /* scaleFactor */); } void Arrow3d::RenderArrow(ref_ptr context, ref_ptr mng, dp::MeshObject & mesh, ScreenBase const & screen, gpu::Program program, dp::Color const & color, float dz, float scaleFactor) { gpu::Arrow3dProgramParams params; math::Matrix const modelTransform = CalculateTransform(screen, dz, scaleFactor); params.m_transform = glsl::make_mat4(modelTransform.m_data); params.m_color = glsl::ToVec4(color); auto gpuProgram = mng->GetProgram(program); mesh.Render(context, gpuProgram, m_state, mng->GetParamsSetter(), params); } math::Matrix Arrow3d::CalculateTransform(ScreenBase const & screen, float dz, float scaleFactor) const { double arrowScale = VisualParams::Instance().GetVisualScale() * kArrowSize * scaleFactor; if (screen.isPerspective()) { double const t = GetNormalizedZoomLevel(screen.GetScale(), kArrow3dMinZoom); arrowScale *= (kArrow3dScaleMin * (1.0 - t) + kArrow3dScaleMax * t); } auto const scaleX = static_cast(arrowScale * 2.0 / screen.PixelRect().SizeX()); auto const scaleY = static_cast(arrowScale * 2.0 / screen.PixelRect().SizeY()); auto const scaleZ = static_cast(screen.isPerspective() ? (0.002 * screen.GetDepth3d()) : 1.0); m2::PointD const pos = screen.GtoP(m_position); auto const dX = static_cast(2.0 * pos.x / screen.PixelRect().SizeX() - 1.0); auto const dY = static_cast(2.0 * pos.y / screen.PixelRect().SizeY() - 1.0); math::Matrix scaleM = math::Identity(); scaleM(0, 0) = scaleX; scaleM(1, 1) = scaleY; scaleM(2, 2) = scaleZ; math::Matrix rotateM = math::Identity(); rotateM(0, 0) = static_cast(cos(m_azimuth + screen.GetAngle())); rotateM(0, 1) = static_cast(-sin(m_azimuth + screen.GetAngle())); rotateM(1, 0) = -rotateM(0, 1); rotateM(1, 1) = rotateM(0, 0); math::Matrix translateM = math::Identity(); translateM(3, 0) = dX; translateM(3, 1) = -dY; translateM(3, 2) = dz; math::Matrix modelTransform = rotateM * scaleM * translateM; if (screen.isPerspective()) return modelTransform * math::Matrix(screen.Pto3dMatrix()); return modelTransform; } } // namespace df