Beispiel #1
0
void Arrow3d::Render(ScreenBase const & screen, int zoomLevel, ref_ptr<dp::GpuProgramManager> mng)
{
    // Unbind current VAO, because glVertexAttributePointer and glEnableVertexAttribute can affect it.
    if (dp::GLExtensionsList::Instance().IsSupported(dp::GLExtensionsList::VertexArrayObject))
        GLFunctions::glBindVertexArray(0);

    if (!m_isInitialized)
    {
        Build();
        m_isInitialized = true;
    }

    // Render shadow.
    if (screen.isPerspective())
    {
        ref_ptr<dp::GpuProgram> shadowProgram = mng->GetProgram(gpu::ARROW_3D_SHADOW_PROGRAM);
        RenderArrow(screen, shadowProgram, dp::Color(60, 60, 60, 60), 0.05f, false /* hasNormals */);
    }

    // Render arrow.
    ref_ptr<dp::GpuProgram> arrowProgram = mng->GetProgram(gpu::ARROW_3D_PROGRAM);
    dp::Color const color = df::GetColorConstant(GetStyleReader().GetCurrentStyle(),
                            m_obsoletePosition ? df::Arrow3DObsolete : df::Arrow3D);
    RenderArrow(screen, arrowProgram, color, 0.0f, true /* hasNormals */);

    arrowProgram->Unbind();
    GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer);
}
Beispiel #2
0
void SelectionShape::Render(ScreenBase const & screen, int zoomLevel, ref_ptr<dp::GpuProgramManager> mng,
                            dp::UniformValuesStorage const & commonUniforms)
{
  ShowHideAnimation::EState state = m_animation.GetState();
  if (state == ShowHideAnimation::STATE_VISIBLE ||
      state == ShowHideAnimation::STATE_SHOW_DIRECTION)
  {
    dp::UniformValuesStorage uniforms = commonUniforms;
    TileKey const key = GetTileKeyByPoint(m_position, ClipTileZoomByMaxDataZoom(zoomLevel));
    math::Matrix<float, 4, 4> mv = key.GetTileBasedModelView(screen);
    uniforms.SetMatrix4x4Value("modelView", mv.m_data);

    m2::PointD const pos = MapShape::ConvertToLocal(m_position, key.GetGlobalRect().Center(), kShapeCoordScalar);
    uniforms.SetFloatValue("u_position", pos.x, pos.y, -m_positionZ);

    float accuracy = m_mapping.GetValue(m_animation.GetT());
    if (screen.isPerspective())
    {
      m2::PointD const pt1 = screen.GtoP(m_position);
      m2::PointD const pt2(pt1.x + 1, pt1.y);
      float const scale = screen.PtoP3d(pt2).x - screen.PtoP3d(pt1).x;
      accuracy /= scale;
    }
    uniforms.SetFloatValue("u_accuracy", accuracy);
    uniforms.SetFloatValue("u_opacity", 1.0f);
    m_renderNode->Render(mng, uniforms);
  }
}
Beispiel #3
0
void BaseRenderGroup::Render(const ScreenBase & screen)
{
  ref_ptr<dp::GpuProgram> shader = screen.isPerspective() ? m_shader3d : m_shader;
  ASSERT(shader != nullptr, ());
  ASSERT(m_generalUniforms != nullptr, ());

  shader->Bind();
  dp::ApplyState(m_state, shader);
  dp::ApplyUniforms(*(m_generalUniforms.get()), shader);
}
Beispiel #4
0
math::Matrix<float, 4, 4> Arrow3d::CalculateTransform(ScreenBase const & screen, float dz) const
{
    double arrowScale = VisualParams::Instance().GetVisualScale() * kArrowSize;
    if (screen.isPerspective())
    {
        static double const kLog2 = log(2.0);
        double const kMaxZoom = scales::UPPER_STYLE_SCALE + 1.0;
        double const zoomLevel = my::clamp(fabs(log(screen.GetScale()) / kLog2), kArrow3dMinZoom, kMaxZoom);
        double const t = (zoomLevel - kArrow3dMinZoom) / (kMaxZoom - kArrow3dMinZoom);
        arrowScale *= (kArrow3dScaleMin * (1.0 - t) + kArrow3dScaleMax * t);
    }

    double const scaleX = arrowScale * 2.0 / screen.PixelRect().SizeX();
    double const scaleY = arrowScale * 2.0 / screen.PixelRect().SizeY();
    double const scaleZ = screen.isPerspective() ? (0.002 * screen.GetDepth3d()) : 1.0;

    m2::PointD const pos = screen.GtoP(m_position);
    double const dX = 2.0 * pos.x / screen.PixelRect().SizeX() - 1.0;
    double const dY = 2.0 * pos.y / screen.PixelRect().SizeY() - 1.0;

    math::Matrix<float, 4, 4> scaleM = math::Identity<float, 4>();
    scaleM(0, 0) = scaleX;
    scaleM(1, 1) = scaleY;
    scaleM(2, 2) = scaleZ;

    math::Matrix<float, 4, 4> rotateM = math::Identity<float, 4>();
    rotateM(0, 0) = cos(m_azimuth + screen.GetAngle());
    rotateM(0, 1) = -sin(m_azimuth + screen.GetAngle());
    rotateM(1, 0) = -rotateM(0, 1);
    rotateM(1, 1) = rotateM(0, 0);

    math::Matrix<float, 4, 4> translateM = math::Identity<float, 4>();
    translateM(3, 0) = dX;
    translateM(3, 1) = -dY;
    translateM(3, 2) = dz;

    math::Matrix<float, 4, 4> modelTransform = rotateM * scaleM * translateM;
    if (screen.isPerspective())
        return modelTransform * math::Matrix<float, 4, 4>(screen.Pto3dMatrix());

    return modelTransform;
}
Beispiel #5
0
void FrontendRenderer::OnResize(ScreenBase const & screen)
{
  m2::RectD const viewportRect = screen.isPerspective() ? screen.PixelRectIn3d() : screen.PixelRect();

  m_myPositionController->UpdatePixelPosition(screen);
  m_myPositionController->OnNewPixelRect();

  m_viewport.SetViewport(0, 0, viewportRect.SizeX(), viewportRect.SizeY());
  m_contextFactory->getDrawContext()->resize(viewportRect.SizeX(), viewportRect.SizeY());
  RefreshProjection(screen);
  RefreshPivotTransform(screen);

  m_framebuffer->SetSize(viewportRect.SizeX(), viewportRect.SizeY());
}
Beispiel #6
0
void MyPosition::RenderMyPosition(ScreenBase const & screen,
                                  ref_ptr<dp::GpuProgramManager> mng,
                                  dp::UniformValuesStorage const & commonUniforms)
{
  if (screen.isPerspective() && m_isRoutingMode && m_showAzimuth)
  {
    m_arrow3d.SetPosition(m_position);
    m_arrow3d.SetAzimuth(m_azimuth);

    m_arrow3d.Render(screen, mng);
  }
  else
  {
    dp::UniformValuesStorage uniforms = commonUniforms;
    uniforms.SetFloatValue("u_position", m_position.x, m_position.y, dp::depth::MY_POSITION_MARK);
    uniforms.SetFloatValue("u_azimut", -(m_azimuth + screen.GetAngle()));
    uniforms.SetFloatValue("u_opacity", 1.0);
    RenderPart(mng, uniforms, (m_showAzimuth == true) ?
                              (m_obsoletePosition ? MY_POSITION_ARROW_GRAY : MY_POSITION_ARROW) :
                              MY_POSITION_POINT);
  }
}
Beispiel #7
0
void SelectionShape::Render(ScreenBase const & screen, ref_ptr<dp::GpuProgramManager> mng,
                            dp::UniformValuesStorage const & commonUniforms)
{
  ShowHideAnimation::EState state = m_animation.GetState();
  if (state == ShowHideAnimation::STATE_VISIBLE ||
      state == ShowHideAnimation::STATE_SHOW_DIRECTION)
  {
    dp::UniformValuesStorage uniforms = commonUniforms;
    uniforms.SetFloatValue("u_position", m_position.x, m_position.y, -m_positionZ);

    float accuracy = m_mapping.GetValue(m_animation.GetT());
    if (screen.isPerspective())
    {
      m2::PointD const pt1 = screen.GtoP(m_position);
      m2::PointD const pt2(pt1.x + 1, pt1.y);
      float const scale = screen.PtoP3d(pt2).x - screen.PtoP3d(pt1).x;
      accuracy /= scale;
    }
    uniforms.SetFloatValue("u_accuracy", accuracy);
    uniforms.SetFloatValue("u_opacity", 1.0f);
    m_renderNode->Render(mng, uniforms);
  }
}
Beispiel #8
0
void MyPositionController::UpdatePixelPosition(ScreenBase const & screen)
{
  m_pixelRect = screen.isPerspective() ? screen.PixelRectIn3d() : screen.PixelRect();
  m_positionYOffset = screen.isPerspective() ? kPositionOffsetYIn3D : kPositionOffsetY;
}
Beispiel #9
0
void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
{
  switch (message->GetType())
  {
  case Message::FlushTile:
    {
      ref_ptr<FlushRenderBucketMessage> msg = message;
      dp::GLState const & state = msg->GetState();
      TileKey const & key = msg->GetKey();
      drape_ptr<dp::RenderBucket> bucket = msg->AcceptBuffer();
      ref_ptr<dp::GpuProgram> program = m_gpuProgramManager->GetProgram(state.GetProgramIndex());
      ref_ptr<dp::GpuProgram> program3d = m_gpuProgramManager->GetProgram(state.GetProgram3dIndex());
      bool const isPerspective = m_userEventStream.GetCurrentScreen().isPerspective();
      if (isPerspective)
        program3d->Bind();
      else
        program->Bind();
      bucket->GetBuffer()->Build(isPerspective ? program3d : program);
      if (!IsUserMarkLayer(key))
      {
        if (CheckTileGenerations(key))
          m_tileTree->ProcessTile(key, GetCurrentZoomLevelForData(), state, move(bucket));
      }
      else
      {
        m_userMarkRenderGroups.emplace_back(make_unique_dp<UserMarkRenderGroup>(state, key, move(bucket)));
        m_userMarkRenderGroups.back()->SetRenderParams(program, program3d, make_ref(&m_generalUniforms));
      }
      break;
    }

  case Message::FinishReading:
    {
      ref_ptr<FinishReadingMessage> msg = message;
      for (auto const & tileKey : msg->GetTiles())
        CheckTileGenerations(tileKey);
      m_tileTree->FinishTiles(msg->GetTiles(), GetCurrentZoomLevelForData());
      break;
    }

  case Message::InvalidateRect:
    {
      ref_ptr<InvalidateRectMessage> m = message;
      TTilesCollection tiles;
      ScreenBase screen = m_userEventStream.GetCurrentScreen();
      m2::RectD rect = m->GetRect();
      if (rect.Intersect(screen.ClipRect()))
      {
        m_tileTree->Invalidate();
        ResolveTileKeys(rect, tiles);

        auto eraseFunction = [&tiles](vector<drape_ptr<RenderGroup>> & groups)
        {
          vector<drape_ptr<RenderGroup> > newGroups;
          for (drape_ptr<RenderGroup> & group : groups)
          {
            if (tiles.find(group->GetTileKey()) == tiles.end())
              newGroups.push_back(move(group));
          }

          swap(groups, newGroups);
        };

        eraseFunction(m_renderGroups);
        eraseFunction(m_deferredRenderGroups);

        BaseBlockingMessage::Blocker blocker;
        m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
                                  make_unique_dp<InvalidateReadManagerRectMessage>(blocker, tiles),
                                  MessagePriority::High);
        blocker.Wait();

        m_requestedTiles->Set(screen, m_isIsometry || screen.isPerspective(), move(tiles));
        m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
                                  make_unique_dp<UpdateReadManagerMessage>(),
                                  MessagePriority::UberHighSingleton);
      }
      break;
    }

  case Message::ClearUserMarkLayer:
    {
      TileKey const & tileKey = ref_ptr<ClearUserMarkLayerMessage>(message)->GetKey();
      auto const functor = [&tileKey](drape_ptr<UserMarkRenderGroup> const & g)
      {
        return g->GetTileKey() == tileKey;
      };

      auto const iter = remove_if(m_userMarkRenderGroups.begin(),
                                  m_userMarkRenderGroups.end(),
                                  functor);

      m_userMarkRenderGroups.erase(iter, m_userMarkRenderGroups.end());
      break;
    }

  case Message::ChangeUserMarkLayerVisibility:
    {
      ref_ptr<ChangeUserMarkLayerVisibilityMessage> m = message;
      TileKey const & key = m->GetKey();
      if (m->IsVisible())
        m_userMarkVisibility.insert(key);
      else
        m_userMarkVisibility.erase(key);
      break;
    }

  case Message::GuiLayerRecached:
    {
      ref_ptr<GuiLayerRecachedMessage> msg = message;
      drape_ptr<gui::LayerRenderer> renderer = move(msg->AcceptRenderer());
      renderer->Build(make_ref(m_gpuProgramManager));
      if (m_guiRenderer == nullptr)
        m_guiRenderer = move(renderer);
      else
        m_guiRenderer->Merge(make_ref(renderer));
      break;
    }

  case Message::GuiLayerLayout:
    {
      ASSERT(m_guiRenderer != nullptr, ());
      m_guiRenderer->SetLayout(ref_ptr<GuiLayerLayoutMessage>(message)->GetLayoutInfo());
      break;
    }

  case Message::StopRendering:
    {
      ProcessStopRenderingMessage();
      break;
    }

  case Message::MyPositionShape:
    {
      ref_ptr<MyPositionShapeMessage> msg = message;
      m_myPositionController->SetRenderShape(msg->AcceptShape());
      m_selectionShape = msg->AcceptSelection();
    }
    break;

  case Message::ChangeMyPostitionMode:
    {
      ref_ptr<ChangeMyPositionModeMessage> msg = message;
      switch (msg->GetChangeType())
      {
      case ChangeMyPositionModeMessage::TYPE_NEXT:
        m_myPositionController->NextMode(msg->GetPreferredZoomLevel());
        break;
      case ChangeMyPositionModeMessage::TYPE_STOP_FOLLOW:
        m_myPositionController->StopLocationFollow();
        break;
      case ChangeMyPositionModeMessage::TYPE_INVALIDATE:
        m_myPositionController->Invalidate();
        break;
      case ChangeMyPositionModeMessage::TYPE_CANCEL:
        m_myPositionController->TurnOff();
        break;
      default:
        ASSERT(false, ("Unknown change type:", static_cast<int>(msg->GetChangeType())));
        break;
      }
      break;
    }

  case Message::CompassInfo:
    {
      ref_ptr<CompassInfoMessage> msg = message;
      m_myPositionController->OnCompassUpdate(msg->GetInfo(), m_userEventStream.GetCurrentScreen());
      break;
    }

  case Message::GpsInfo:
    {
      ref_ptr<GpsInfoMessage> msg = message;
      m_myPositionController->OnLocationUpdate(msg->GetInfo(), msg->IsNavigable(),
                                               m_userEventStream.GetCurrentScreen());

      location::RouteMatchingInfo const & info = msg->GetRouteInfo();
      if (info.HasDistanceFromBegin())
        m_routeRenderer->UpdateDistanceFromBegin(info.GetDistanceFromBegin());

      break;
    }

  case Message::FindVisiblePOI:
    {
      ref_ptr<FindVisiblePOIMessage> msg = message;
      ScreenBase const & screen = m_userEventStream.GetCurrentScreen();
      msg->SetFeatureID(GetVisiblePOI(screen.isPerspective() ? screen.PtoP3d(screen.GtoP(msg->GetPoint()))
                                                             : screen.GtoP(msg->GetPoint())));
      break;
    }

  case Message::SelectObject:
    {
      ref_ptr<SelectObjectMessage> msg = message;

      if (m_selectionShape == nullptr)
        break;

      if (msg->IsDismiss())
      {
        m_selectionShape->Hide();
      }
      else
      {
        double offsetZ = 0.0;
        if (m_userEventStream.GetCurrentScreen().isPerspective())
        {
          dp::OverlayTree::TSelectResult selectResult;
          m_overlayTree->Select(msg->GetPosition(), selectResult);
          for (ref_ptr<dp::OverlayHandle> handle : selectResult)
            offsetZ = max(offsetZ, handle->GetPivotZ());
        }
        m_selectionShape->Show(msg->GetSelectedObject(), msg->GetPosition(), offsetZ, msg->IsAnim());
      }
      break;
    }

  case Message::GetSelectedObject:
    {
      ref_ptr<GetSelectedObjectMessage> msg = message;
      if (m_selectionShape != nullptr)
        msg->SetSelectedObject(m_selectionShape->GetSelectedObject());
      else
        msg->SetSelectedObject(SelectionShape::OBJECT_EMPTY);
      break;
    }

  case Message::GetMyPosition:
    {
      ref_ptr<GetMyPositionMessage> msg = message;
      msg->SetMyPosition(m_myPositionController->IsModeHasPosition(), m_myPositionController->Position());
      break;
    }

  case Message::FlushRoute:
    {
      ref_ptr<FlushRouteMessage> msg = message;
      drape_ptr<RouteData> routeData = msg->AcceptRouteData();
      m2::PointD const startPoint = routeData->m_sourcePolyline.Front();
      m2::PointD const finishPoint = routeData->m_sourcePolyline.Back();
      m_routeRenderer->SetRouteData(move(routeData), make_ref(m_gpuProgramManager));
      if (!m_routeRenderer->GetStartPoint())
      {
        m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
                                  make_unique_dp<CacheRouteSignMessage>(startPoint, true /* isStart */,
                                                                        true /* isValid */),
                                  MessagePriority::High);
      }
      if (!m_routeRenderer->GetFinishPoint())
      {
        m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
                                  make_unique_dp<CacheRouteSignMessage>(finishPoint, false /* isStart */,
                                                                        true /* isValid */),
                                  MessagePriority::High);
      }

      m_myPositionController->ActivateRouting();
      break;
    }

  case Message::FlushRouteSign:
    {
      ref_ptr<FlushRouteSignMessage> msg = message;
      drape_ptr<RouteSignData> routeSignData = msg->AcceptRouteSignData();
      m_routeRenderer->SetRouteSign(move(routeSignData), make_ref(m_gpuProgramManager));
      break;
    }

  case Message::RemoveRoute:
    {
      ref_ptr<RemoveRouteMessage> msg = message;
      m_routeRenderer->Clear();
      if (msg->NeedDeactivateFollowing())
      {
        m_myPositionController->DeactivateRouting();
        m_overlayTree->SetFollowingMode(false);
        if (m_enablePerspectiveInNavigation)
          DisablePerspective();
      }
      break;
    }

  case Message::FollowRoute:
    {
      ref_ptr<FollowRouteMessage> const msg = message;
      m_myPositionController->NextMode(!m_enablePerspectiveInNavigation ? msg->GetPreferredZoomLevel()
                                                               : msg->GetPreferredZoomLevelIn3d());
      m_overlayTree->SetFollowingMode(true);
      if (m_enablePerspectiveInNavigation)
      {
        bool immediatelyStart = !m_myPositionController->IsRotationActive();
        AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(),
                                            true /* animated */, immediatelyStart));
      }
      break;
    }

  case Message::DeactivateRouteFollowing:
    {
      m_myPositionController->DeactivateRouting();
      m_overlayTree->SetFollowingMode(false);
      if (m_enablePerspectiveInNavigation)
        DisablePerspective();
      break;
    }

  case Message::UpdateMapStyle:
    {
      // Clear tile tree.
      m_tileTree->Invalidate();

      // Get new tiles.
      TTilesCollection tiles;
      ScreenBase screen = m_userEventStream.GetCurrentScreen();
      ResolveTileKeys(screen.ClipRect(), tiles);

      // Clear all graphics.
      m_renderGroups.clear();
      m_deferredRenderGroups.clear();

      // Invalidate read manager.
      {
        BaseBlockingMessage::Blocker blocker;
        m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
                                  make_unique_dp<InvalidateReadManagerRectMessage>(blocker, tiles),
                                  MessagePriority::High);
        blocker.Wait();
      }

      // Invalidate textures and wait for completion.
      {
        BaseBlockingMessage::Blocker blocker;
        m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
                                  make_unique_dp<InvalidateTexturesMessage>(blocker),
                                  MessagePriority::High);
        blocker.Wait();
      }

      // 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 */),
                                  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 */),
                                  MessagePriority::High);
      }

      auto const & routeData = m_routeRenderer->GetRouteData();
      if (routeData != nullptr)
      {
        auto recacheRouteMsg = make_unique_dp<AddRouteMessage>(routeData->m_sourcePolyline,
                                                               routeData->m_sourceTurns,
                                                               routeData->m_color);
        m_routeRenderer->Clear(true /* keepDistanceFromBegin */);
        m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread, move(recacheRouteMsg),
                                  MessagePriority::Normal);
      }

      // Request new tiles.
      m_requestedTiles->Set(screen, m_isIsometry || screen.isPerspective(), move(tiles));
      m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
                                make_unique_dp<UpdateReadManagerMessage>(),
                                MessagePriority::UberHighSingleton);
      break;
    }

  case Message::EnablePerspective:
    {
      ref_ptr<EnablePerspectiveMessage> const msg = message;
      AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(),
                                          false /* animated */, true /* immediately start */));
      break;
    }

  case Message::Allow3dMode:
    {
      ref_ptr<Allow3dModeMessage> const msg = message;
      bool const isPerspective = m_userEventStream.GetCurrentScreen().isPerspective();
#ifdef OMIM_OS_DESKTOP
      if (m_enablePerspectiveInNavigation == msg->AllowPerspective() &&
          m_enablePerspectiveInNavigation != isPerspective)
      {
        if (m_enablePerspectiveInNavigation)
          AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(),
                                              false /* animated */, true /* immediately start */));
        else
          AddUserEvent(DisablePerspectiveEvent());
      }
#endif
      m_enablePerspectiveInNavigation = msg->AllowPerspective();
      m_enable3dBuildings = msg->Allow3dBuildings();

      if (m_myPositionController->IsInRouting())
      {
        if (m_enablePerspectiveInNavigation && !isPerspective && !m_perspectiveDiscarded)
        {
          AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(),
                                              true /* animated */, true /* immediately start */));
        }
        else if (!m_enablePerspectiveInNavigation && (isPerspective || m_perspectiveDiscarded))
        {
          DisablePerspective();
        }
      }
      break;
    }

  case Message::Invalidate:
    {
      // Do nothing here, new frame will be rendered because of this message processing.
      break;
    }

  default:
    ASSERT(false, ());
  }
}