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); }
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); } }
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); }
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; }
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()); }
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); } }
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); } }
void MyPositionController::UpdatePixelPosition(ScreenBase const & screen) { m_pixelRect = screen.isPerspective() ? screen.PixelRectIn3d() : screen.PixelRect(); m_positionYOffset = screen.isPerspective() ? kPositionOffsetYIn3D : kPositionOffsetY; }
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, ()); } }