Skip to content

Commit

Permalink
Overlays clipping for perspective mode.
Browse files Browse the repository at this point in the history
Conflicts:
	drape/overlay_handle.cpp
	drape/overlay_handle.hpp
	drape/overlay_tree.cpp
	drape_frontend/poi_symbol_shape.cpp
	drape_frontend/text_shape.cpp
  • Loading branch information
darina committed Dec 29, 2015
1 parent 3a0d040 commit 9b5abcb
Show file tree
Hide file tree
Showing 20 changed files with 306 additions and 234 deletions.
100 changes: 95 additions & 5 deletions drape/overlay_handle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ struct OverlayHandle::OffsetNodeFinder
uint8_t m_bufferID;
};

OverlayHandle::OverlayHandle(FeatureID const & id, dp::Anchor anchor, uint64_t priority)
OverlayHandle::OverlayHandle(FeatureID const & id,
dp::Anchor anchor,
uint64_t priority,
bool isBillboard)
: m_id(id)
, m_anchor(anchor)
, m_priority(priority)
, m_isBillboard(isBillboard)
, m_overlayRank(OverlayRank0)
, m_extendingSize(0)
, m_isVisible(false)
Expand All @@ -41,6 +45,11 @@ void OverlayHandle::SetIsVisible(bool isVisible)
m_visibilityTimestamp = steady_clock::now();
}

bool OverlayHandle::IsBillboard() const
{
return m_isBillboard;
}

m2::PointD OverlayHandle::GetPivot(ScreenBase const & screen) const
{
m2::RectD r = GetPixelRect(screen);
Expand All @@ -60,6 +69,11 @@ m2::PointD OverlayHandle::GetPivot(ScreenBase const & screen) const
return result;
}

m2::PointD OverlayHandle::GetPivotPerspective(ScreenBase const & screen) const
{
return GetPerspectivePoint(GetPivot(screen), screen);
}

bool OverlayHandle::IsIntersect(ScreenBase const & screen, ref_ptr<OverlayHandle> const h) const
{
Rects ar1;
Expand Down Expand Up @@ -126,14 +140,19 @@ OverlayHandle::TOffsetNode const & OverlayHandle::GetOffsetNode(uint8_t bufferID

m2::RectD OverlayHandle::GetExtendedPixelRect(ScreenBase const & screen) const
{
m2::RectD rect = GetPixelRect(screen);
m2::RectD rect = screen.isPerspective() ? GetPixelRectPerspective(screen)
: GetPixelRect(screen);
rect.Inflate(m_extendingSize, m_extendingSize);
return rect;
}

void OverlayHandle::GetExtendedPixelShape(ScreenBase const & screen, Rects & rects) const
{
GetPixelShape(screen, rects);
if (screen.isPerspective())
GetPixelShapePerspective(screen, rects);
else
GetPixelShape(screen, rects);

for (auto & rect : rects)
rect.Inflate(m_extendingSize, m_extendingSize);
}
Expand All @@ -145,10 +164,75 @@ bool OverlayHandle::IsMinVisibilityTimeUp() const
return t > kMinVisibilityTimeMs;
}

m2::PointD OverlayHandle::GetPerspectivePoint(m2::PointD const & pixelPoint, ScreenBase const & screen) const
{
m2::RectD screenPixelRect = screen.PixelRect();
ASSERT(screenPixelRect.SizeX() && screenPixelRect.SizeY(), ());

math::Matrix<double, 1, 4> normalizedPoint
{
float(2.0 * pixelPoint.x / screenPixelRect.SizeX() - 1.0),
-float(2.0 * pixelPoint.y / screenPixelRect.SizeY() - 1.0),
0.0,
1.0
};

math::Matrix<double, 1, 4> perspectivePivot = normalizedPoint * screen.PTo3dMatrix();
perspectivePivot(0, 0) /= perspectivePivot(0, 3);
perspectivePivot(0, 1) /= perspectivePivot(0, 3);
perspectivePivot(0, 2) /= perspectivePivot(0, 3);
perspectivePivot(0, 3) = 1.0;

m2::RectD viewport = screen.PixelRect3d();
m2::PointD pixelPointPerspective(
(perspectivePivot(0, 0) + 1.0) * viewport.SizeX() / 2.0,
(perspectivePivot(0, 1) + 1.0) * viewport.SizeY() / 2.0);

return pixelPointPerspective;
}

m2::RectD OverlayHandle::GetPerspectiveRect(const m2::RectD & pixelRect, ScreenBase const & screen) const
{
m2::PointD tmpPoint = GetPerspectivePoint(pixelRect.LeftTop(), screen);
m2::RectD perspectiveRect(tmpPoint, tmpPoint);

tmpPoint = GetPerspectivePoint(pixelRect.RightBottom(), screen);
perspectiveRect.Add(tmpPoint);

tmpPoint = GetPerspectivePoint(m2::PointD(pixelRect.minX(), pixelRect.maxY()), screen);
perspectiveRect.Add(tmpPoint);

tmpPoint = GetPerspectivePoint(m2::PointD(pixelRect.maxX(), pixelRect.minY()), screen);
perspectiveRect.Add(tmpPoint);

return perspectiveRect;
}

m2::RectD OverlayHandle::GetPixelRectPerspective(ScreenBase const & screen) const
{
if (m_isBillboard)
{
m2::PointD const pxPivot = GetPivot(screen);
m2::PointD pxPivotPerspective = GetPerspectivePoint(pxPivot, screen);

m2::RectD pxRectPerspective = GetPixelRect(screen);
pxRectPerspective.Offset(-pxPivot);
double maxY = -pxRectPerspective.minY();
pxRectPerspective.setMinY(-pxRectPerspective.maxY());
pxRectPerspective.setMaxY(maxY);
pxRectPerspective.Offset(pxPivotPerspective);

return pxRectPerspective;
}

return GetPerspectiveRect(GetPixelRect(screen), screen);
}

SquareHandle::SquareHandle(FeatureID const & id, dp::Anchor anchor,
m2::PointD const & gbPivot, m2::PointD const & pxSize,
uint64_t priority)
: TBase(id, anchor, priority)
uint64_t priority,
bool isBillboard)
: TBase(id, anchor, priority, isBillboard)
, m_gbPivot(gbPivot)
, m_pxHalfSize(pxSize.x / 2.0, pxSize.y / 2.0)
{}
Expand Down Expand Up @@ -179,6 +263,12 @@ void SquareHandle::GetPixelShape(ScreenBase const & screen, Rects & rects) const
rects.push_back(m2::RectF(rd.minX(), rd.minY(), rd.maxX(), rd.maxY()));
}

void SquareHandle::GetPixelShapePerspective(ScreenBase const & screen, Rects & rects) const
{
m2::RectD rd = TBase::GetPixelRectPerspective(screen);
rects.push_back(m2::RectF(rd.minX(), rd.minY(), rd.maxX(), rd.maxY()));
}

uint64_t CalculateOverlayPriority(int minZoomLevel, uint8_t rank, float depth)
{
// Overlay priority consider the following:
Expand Down
24 changes: 20 additions & 4 deletions drape/overlay_handle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,28 @@ class OverlayHandle
public:
typedef vector<m2::RectF> Rects;

OverlayHandle(FeatureID const & id, dp::Anchor anchor, uint64_t priority);
OverlayHandle(FeatureID const & id,
dp::Anchor anchor,
uint64_t priority,
bool isBillboard = false);

virtual ~OverlayHandle() {}

bool IsVisible() const;
void SetIsVisible(bool isVisible);

bool IsBillboard() const;

m2::PointD GetPivot(ScreenBase const & screen) const;
m2::PointD GetPivotPerspective(ScreenBase const & screen) const;

virtual bool Update(ScreenBase const & /*screen*/) { return true; }

virtual m2::RectD GetPixelRect(ScreenBase const & screen) const = 0;
virtual m2::RectD GetPixelRectPerspective(ScreenBase const & screen) const;

virtual void GetPixelShape(ScreenBase const & screen, Rects & rects) const = 0;
virtual void GetPixelShapePerspective(ScreenBase const & screen, Rects & rects) const = 0;

double GetExtendingSize() const { return m_extendingSize; }
void SetExtendingSize(double extendingSize) { m_extendingSize = extendingSize; }
Expand Down Expand Up @@ -84,6 +94,7 @@ class OverlayHandle
FeatureID const m_id;
dp::Anchor const m_anchor;
uint64_t const m_priority;
bool m_isBillboard;

int m_overlayRank;
double m_extendingSize;
Expand All @@ -93,6 +104,9 @@ class OverlayHandle
typedef pair<BindingInfo, MutateRegion> TOffsetNode;
TOffsetNode const & GetOffsetNode(uint8_t bufferID) const;

m2::PointD GetPerspectivePoint(const m2::PointD & pixelPoint, ScreenBase const & screen) const;
m2::RectD GetPerspectiveRect(const m2::RectD & pixelRect, ScreenBase const & screen) const;

private:
bool m_isVisible;

Expand All @@ -119,11 +133,13 @@ class SquareHandle : public OverlayHandle
dp::Anchor anchor,
m2::PointD const & gbPivot,
m2::PointD const & pxSize,
uint64_t priority);
uint64_t priority,
bool isBillboard = false);

virtual m2::RectD GetPixelRect(ScreenBase const & screen) const;
virtual void GetPixelShape(ScreenBase const & screen, Rects & rects) const;
virtual m2::RectD GetPixelRect(ScreenBase const & screen) const override;

virtual void GetPixelShape(ScreenBase const & screen, Rects & rects) const override;
virtual void GetPixelShapePerspective(ScreenBase const & screen, Rects & rects) const override;
private:
m2::PointD m_gbPivot;
m2::PointD m_pxHalfSize;
Expand Down
11 changes: 9 additions & 2 deletions drape/overlay_tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,17 @@ void OverlayTree::Add(ref_ptr<OverlayHandle> handle)
ASSERT(IsNeedUpdate(), ());

ScreenBase const & modelView = GetModelView();
bool is3dMode = modelView.isPerspective();

handle->SetIsVisible(false);

if (!handle->Update(modelView))
return;

m2::RectD const pixelRect = handle->GetExtendedPixelRect(modelView);
if (!m_traits.m_modelView.PixelRect().IsIntersect(pixelRect))
m2::RectD const screenRect = is3dMode ? modelView.PixelRect3d()
: modelView.PixelRect();
if (!screenRect.IsIntersect(pixelRect))
{
handle->SetIsVisible(false);
return;
Expand All @@ -112,6 +115,8 @@ void OverlayTree::InsertHandle(ref_ptr<OverlayHandle> handle,
ASSERT(IsNeedUpdate(), ());

ScreenBase const & modelView = GetModelView();
bool is3dMode = modelView.isPerspective();

m2::RectD const pixelRect = handle->GetExtendedPixelRect(modelView);

TOverlayContainer elements;
Expand All @@ -134,15 +139,17 @@ void OverlayTree::InsertHandle(ref_ptr<OverlayHandle> handle,
if (boundToParent)
handleToCompare = parentOverlay.m_handle;

double const posY = is3dMode ? handleToCompare->GetPivotPerspective(modelView).y : 0.0;
// In this loop we decide which element must be visible.
// If input element "handle" more priority than all "Intersected elements"
// than we remove all "Intersected elements" and insert input element "handle".
// But if some of already inserted elements more priority than we don't insert "handle".
HandleComparator comparator;
for (auto const & info : elements)
{
bool rejectByDepth = is3dMode ? posY > info.m_handle->GetPivotPerspective(modelView).y : false;
bool const timeReject = !info.m_handle->IsMinVisibilityTimeUp();
if (timeReject || comparator.IsGreater(info.m_handle, handleToCompare))
if (timeReject || rejectByDepth || comparator.IsGreater(info.m_handle, handleToCompare))
{
// Handle is displaced and bound to its parent, parent will be displaced too.
if (boundToParent)
Expand Down
38 changes: 16 additions & 22 deletions drape_frontend/frontend_renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -469,11 +469,9 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
if (!m_useFramebuffer)
{
ref_ptr<Enable3dModeMessage> msg = message;
m_renderer3d->SetVerticalFOV(msg->GetAngleFOV());
m_renderer3d->SetPlaneAngleX(msg->GetAngleX());
AddUserEvent(Enable3dModeEvent(msg->GetAngleX(), msg->GetAngleFOV()));
m_useFramebuffer = true;
m_3dModeChanged = true;
AddUserEvent(Enable3dModeEvent(max(m_renderer3d->GetScaleX(), m_renderer3d->GetScaleY())));
}
break;
}
Expand Down Expand Up @@ -507,10 +505,12 @@ unique_ptr<threads::IRoutine> FrontendRenderer::CreateRoutine()

void FrontendRenderer::OnResize(ScreenBase const & screen)
{
m2::RectD viewportRect = screen.isPerspective() ? screen.PixelRect3d() : screen.PixelRect();

m_myPositionController->SetPixelRect(screen.PixelRect());

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

if (m_useFramebuffer)
Expand All @@ -522,16 +522,16 @@ void FrontendRenderer::OnResize(ScreenBase const & screen)
{
width = width * m_framebuffer->GetMaxSize() / maxSide;
height = height * m_framebuffer->GetMaxSize() / maxSide;
LOG(LINFO, ("Max texture size: ", m_framebuffer->GetMaxSize(), ", expanded screen size: ", maxSide, ", scale: ", m_framebuffer->GetMaxSize() / (double)maxSide));
}
LOG(LINFO, ("Max texture size: ", m_framebuffer->GetMaxSize(), ", max side: ", maxSide, ", scale: ", m_framebuffer->GetMaxSize() / (double)maxSide));

m_viewport.SetViewport(0, 0, width, height);

m_renderer3d->SetSize(m_pixelRect.SizeX(), m_pixelRect.SizeY());
m_renderer3d->SetSize(viewportRect.SizeX(), viewportRect.SizeY());
m_framebuffer->SetDefaultContext(m_contextFactory->getDrawContext());
m_framebuffer->SetSize(width, height);

RefreshPivotTransform();
RefreshPivotTransform(screen);
}
}

Expand Down Expand Up @@ -793,7 +793,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
if (m_useFramebuffer)
{
m_framebuffer->Disable();
m_renderer3d->Render(m_framebuffer->GetTextureId(), make_ref(m_gpuProgramManager));
m_renderer3d->Render(modelView, m_framebuffer->GetTextureId(), make_ref(m_gpuProgramManager));
// Test code to check ortho overlays in 3d mode
m_isSpriteRenderPass = true;
GLFunctions::glDisable(gl_const::GLDepthTest);
Expand Down Expand Up @@ -834,8 +834,7 @@ void FrontendRenderer::RenderSingleGroup(ScreenBase const & modelView, ref_ptr<B
dp::GLState const & state = group->GetState();
bool isSpriteProgram = IsSpriteProgram(state.GetProgramIndex());

if ((m_isSpriteRenderPass && !isSpriteProgram) ||
(m_useFramebuffer && !m_isSpriteRenderPass && isSpriteProgram))
if (m_useFramebuffer && (m_isSpriteRenderPass != isSpriteProgram))
return;

group->UpdateAnimation();
Expand Down Expand Up @@ -865,10 +864,14 @@ void FrontendRenderer::RefreshModelView(ScreenBase const & screen)
m_generalUniforms.SetMatrix4x4Value("modelView", mv.m_data);
}

void FrontendRenderer::RefreshPivotTransform()
void FrontendRenderer::RefreshPivotTransform(ScreenBase const & screen)
{
if (m_useFramebuffer)
m_generalUniforms.SetMatrix4x4Value("pivotTransform", m_renderer3d->GetTransform().m_data);
{
float transform[16];
copy(begin(screen.PTo3dMatrix().m_data), end(screen.PTo3dMatrix().m_data), transform);
m_generalUniforms.SetMatrix4x4Value("pivotTransform", transform);
}
else
m_generalUniforms.SetMatrix4x4Value("pivotTransform", math::Identity<float, 4>().m_data);
}
Expand Down Expand Up @@ -1207,26 +1210,17 @@ ScreenBase const & FrontendRenderer::ProcessEvents(bool & modelViewChanged, bool
ScreenBase const & modelView = m_userEventStream.ProcessEvents(modelViewChanged, viewportChanged);
gui::DrapeGui::Instance().SetInUserAction(m_userEventStream.IsInUserAction());

m_pixelRect = modelView.PixelRect();

viewportChanged = viewportChanged || m_3dModeChanged;
m_3dModeChanged = false;

if (m_useFramebuffer)
{
double scale = max(m_renderer3d->GetScaleX(), m_renderer3d->GetScaleY());
m_pixelRect.setMaxX(m_pixelRect.maxX() / scale);
m_pixelRect.setMaxY(m_pixelRect.maxY() / scale);
}

return modelView;
}

void FrontendRenderer::PrepareScene(ScreenBase const & modelView)
{
RefreshModelView(modelView);
RefreshBgColor();
RefreshPivotTransform();
RefreshPivotTransform(modelView);
}

void FrontendRenderer::UpdateScene(ScreenBase const & modelView)
Expand Down
3 changes: 1 addition & 2 deletions drape_frontend/frontend_renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class FrontendRenderer : public BaseRenderer
void RenderSingleGroup(ScreenBase const & modelView, ref_ptr<BaseRenderGroup> group);
void RefreshProjection();
void RefreshModelView(ScreenBase const & screen);
void RefreshPivotTransform();
void RefreshPivotTransform(ScreenBase const & screen);
void RefreshBgColor();

ScreenBase const & ProcessEvents(bool & modelViewChanged, bool & viewportChanged);
Expand Down Expand Up @@ -234,7 +234,6 @@ class FrontendRenderer : public BaseRenderer
bool m_3dModeChanged;
drape_ptr<Framebuffer> m_framebuffer;
drape_ptr<Renderer3d> m_renderer3d;
m2::RectD m_pixelRect;

Viewport m_viewport;
UserEventStream m_userEventStream;
Expand Down
Loading

0 comments on commit 9b5abcb

Please sign in to comment.