Rendering 3d buildings in isometric projection.

This commit is contained in:
Daria Volvenkova 2015-12-30 02:14:17 +03:00
parent b4cdfc11d1
commit 535c6b8502
11 changed files with 73 additions and 47 deletions

View file

@ -97,7 +97,8 @@ void BackendRenderer::AcceptMessage(ref_ptr<Message> message)
if (!tiles.empty())
{
ScreenBase const screen = m_requestedTiles->GetScreen();
m_readManager->UpdateCoverage(screen, tiles, m_texMng);
bool const is3dBuildings = m_requestedTiles->Is3dBuildings();
m_readManager->UpdateCoverage(screen, is3dBuildings, tiles, m_texMng);
gui::CountryStatusHelper & helper = gui::DrapeGui::Instance().GetCountryStatusHelper();
if ((*tiles.begin()).m_zoomLevel > scales::GetUpperWorldScale())

View file

@ -429,14 +429,15 @@ gui::TWidgetsSizeInfo const & DrapeEngine::GetWidgetSizes()
return m_widgetSizes;
}
void DrapeEngine::Allow3dMode(bool allow3d, bool allow3dBuildings, double rotationAngle, double angleFOV)
void DrapeEngine::Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings, double rotationAngle, double angleFOV)
{
m_threadCommutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<Allow3dBuildingsMessage>(allow3d && allow3dBuildings),
make_unique_dp<Allow3dBuildingsMessage>(allow3dBuildings),
MessagePriority::Normal);
m_threadCommutator->PostMessage(ThreadsCommutator::RenderThread,
make_unique_dp<Allow3dModeMessage>(allow3d, rotationAngle, angleFOV),
make_unique_dp<Allow3dModeMessage>(allowPerspectiveInNavigation, allow3dBuildings,
rotationAngle, angleFOV),
MessagePriority::Normal);
}

View file

@ -114,7 +114,7 @@ public:
void SetWidgetLayout(gui::TWidgetsLayoutInfo && info);
gui::TWidgetsSizeInfo const & GetWidgetSizes();
void Allow3dMode(bool allow3d, bool allow3dBuildings, double rotationAngle, double angleFOV);
void Allow3dMode(bool allowPerspectiveInNavigation, bool allow3dBuildings, double rotationAngle, double angleFOV);
void EnablePerspective(double rotationAngle, double angleFOV);
private:

View file

@ -47,7 +47,9 @@ FrontendRenderer::FrontendRenderer(Params const & params)
, m_framebuffer(new Framebuffer())
, m_transparentLayer(new TransparentLayer())
, m_overlayTree(new dp::OverlayTree())
, m_enable3dInNavigation(false)
, m_enablePerspectiveInNavigation(false)
, m_enable3dBuildings(false)
, m_isIsometry(false)
, m_viewport(params.m_viewport)
, m_userEventStream(params.m_isCountryLoadedFn)
, m_modelViewChangedFn(params.m_modelViewChangedFn)
@ -197,7 +199,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
MessagePriority::High);
blocker.Wait();
m_requestedTiles->Set(screen, move(tiles));
m_requestedTiles->Set(screen, m_isIsometry || screen.isPerspective(), move(tiles));
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<UpdateReadManagerMessage>(),
MessagePriority::UberHighSingleton);
@ -403,7 +405,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
{
m_myPositionController->DeactivateRouting();
m_overlayTree->SetFollowingMode(false);
if (m_enable3dInNavigation)
if (m_enablePerspectiveInNavigation)
DisablePerspective();
}
break;
@ -412,10 +414,10 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
case Message::FollowRoute:
{
ref_ptr<FollowRouteMessage> const msg = message;
m_myPositionController->NextMode(!m_enable3dInNavigation ? msg->GetPreferredZoomLevel()
m_myPositionController->NextMode(!m_enablePerspectiveInNavigation ? msg->GetPreferredZoomLevel()
: msg->GetPreferredZoomLevelIn3d());
m_overlayTree->SetFollowingMode(true);
if (m_enable3dInNavigation)
if (m_enablePerspectiveInNavigation)
{
bool immediatelyStart = !m_myPositionController->IsRotationActive();
AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(),
@ -428,7 +430,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
{
m_myPositionController->DeactivateRouting();
m_overlayTree->SetFollowingMode(false);
if (m_enable3dInNavigation)
if (m_enablePerspectiveInNavigation)
DisablePerspective();
break;
}
@ -495,7 +497,7 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
}
// Request new tiles.
m_requestedTiles->Set(screen, move(tiles));
m_requestedTiles->Set(screen, m_isIsometry || screen.isPerspective(), move(tiles));
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<UpdateReadManagerMessage>(),
MessagePriority::UberHighSingleton);
@ -518,27 +520,28 @@ void FrontendRenderer::AcceptMessage(ref_ptr<Message> message)
ref_ptr<Allow3dModeMessage> const msg = message;
bool const isPerspective = m_userEventStream.GetCurrentScreen().isPerspective();
#ifdef OMIM_OS_DESKTOP
if (m_enable3dInNavigation == msg->Allow() &&
m_enable3dInNavigation != isPerspective)
if (m_enablePerspectiveInNavigation == msg->AllowPerspective() &&
m_enablePerspectiveInNavigation != isPerspective)
{
if (m_enable3dInNavigation)
if (m_enablePerspectiveInNavigation)
AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(),
false /* animated */, true /* immediately start */));
else
AddUserEvent(DisablePerspectiveEvent());
}
#endif
m_enable3dInNavigation = msg->Allow();
m_enablePerspectiveInNavigation = msg->AllowPerspective();
m_enable3dBuildings = msg->Allow3dBuildings();
if (m_myPositionController->IsInRouting())
{
if (m_enable3dInNavigation && !isPerspective && !m_perspectiveDiscarded)
if (m_enablePerspectiveInNavigation && !isPerspective && !m_perspectiveDiscarded)
{
AddUserEvent(EnablePerspectiveEvent(msg->GetRotationAngle(), msg->GetAngleFOV(),
true /* animated */, true /* immediately start */));
}
else if (!m_enable3dInNavigation && (isPerspective || m_perspectiveDiscarded))
else if (!m_enablePerspectiveInNavigation && (isPerspective || m_perspectiveDiscarded))
{
DisablePerspective();
}
@ -574,8 +577,7 @@ void FrontendRenderer::OnResize(ScreenBase const & screen)
RefreshProjection(screen);
RefreshPivotTransform(screen);
if (screen.isPerspective())
m_framebuffer->SetSize(viewportRect.SizeX(), viewportRect.SizeY());
m_framebuffer->SetSize(viewportRect.SizeX(), viewportRect.SizeY());
}
void FrontendRenderer::AddToRenderGroup(vector<drape_ptr<RenderGroup>> & groups,
@ -780,7 +782,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
dp::GLState const & state = group->GetState();
if (isPerspective && state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM)
if ((isPerspective || m_isIsometry) && state.GetProgram3dIndex() == gpu::AREA_3D_PROGRAM)
{
if (!has3dAreas)
{
@ -822,7 +824,7 @@ void FrontendRenderer::RenderScene(ScreenBase const & modelView)
m_myPositionController->Render(MyPositionController::RenderAccuracy,
modelView, make_ref(m_gpuProgramManager), m_generalUniforms);
if (isPerspective && has3dAreas)
if (has3dAreas)
{
m_framebuffer->Enable();
GLFunctions::glClear();
@ -938,8 +940,18 @@ void FrontendRenderer::RefreshPivotTransform(ScreenBase const & screen)
math::Matrix<float, 4, 4> transform(screen.Pto3dMatrix());
m_generalUniforms.SetMatrix4x4Value("pivotTransform", transform.m_data);
}
else if (m_isIsometry)
{
math::Matrix<float, 4, 4> transform(math::Identity<float, 4>());
transform(2, 1) = -1.0f/tan(M_PI * 80.0f / 180.0f);
transform(2, 2) = 1.0f / screen.GetHeight();
m_generalUniforms.SetMatrix4x4Value("pivotTransform", transform.m_data);
}
else
m_generalUniforms.SetMatrix4x4Value("pivotTransform", math::Identity<float, 4>().m_data);
{
math::Matrix<float, 4, 4> transform(math::Identity<float, 4>());
m_generalUniforms.SetMatrix4x4Value("pivotTransform", transform.m_data);
}
}
void FrontendRenderer::RefreshBgColor()
@ -968,11 +980,13 @@ void FrontendRenderer::DisablePerspective()
void FrontendRenderer::CheckMinAllowableIn3dScale()
{
if (!m_enable3dInNavigation ||
m_userEventStream.IsInPerspectiveAnimation())
bool const isScaleAllowableIn3d = UserEventStream::IsScaleAllowableIn3d(m_currentZoomLevel);
m_isIsometry = m_enable3dBuildings && isScaleAllowableIn3d;
if (!m_enablePerspectiveInNavigation || m_userEventStream.IsInPerspectiveAnimation())
return;
bool const switchTo2d = !UserEventStream::IsScaleAllowableIn3d(m_currentZoomLevel);
bool const switchTo2d = !isScaleAllowableIn3d;
if ((!switchTo2d && !m_perspectiveDiscarded) ||
(switchTo2d && !m_userEventStream.GetCurrentScreen().isPerspective()))
return;
@ -1328,7 +1342,7 @@ void FrontendRenderer::UpdateScene(ScreenBase const & modelView)
};
RemoveRenderGroups(removePredicate);
m_requestedTiles->Set(modelView, move(tiles));
m_requestedTiles->Set(modelView, m_isIsometry || modelView.isPerspective(), move(tiles));
m_commutator->PostMessage(ThreadsCommutator::ResourceUploadThread,
make_unique_dp<UpdateReadManagerMessage>(),
MessagePriority::UberHighSingleton);

View file

@ -234,7 +234,9 @@ private:
dp::UniformValuesStorage m_generalUniforms;
bool m_enable3dInNavigation;
bool m_enablePerspectiveInNavigation;
bool m_enable3dBuildings;
bool m_isIsometry;
Viewport m_viewport;
UserEventStream m_userEventStream;

View file

@ -656,19 +656,22 @@ public:
class Allow3dModeMessage : public Message
{
public:
Allow3dModeMessage(bool allow, double rotationAngle, double angleFOV)
: m_allow(allow)
Allow3dModeMessage(bool allowPerspective, bool allow3dBuildings, double rotationAngle, double angleFOV)
: m_allowPerspective(allowPerspective)
, m_allow3dBuildings(allow3dBuildings)
, m_rotationAngle(rotationAngle)
, m_angleFOV(angleFOV)
{}
Type GetType() const override { return Message::Allow3dMode; }
bool Allow() const { return m_allow; }
bool AllowPerspective() const { return m_allowPerspective; }
bool Allow3dBuildings() const { return m_allow3dBuildings; }
double GetRotationAngle() const { return m_rotationAngle; }
double GetAngleFOV() const { return m_angleFOV; }
private:
bool const m_allow;
bool const m_allowPerspective;
bool const m_allow3dBuildings;
double const m_rotationAngle;
double const m_angleFOV;
};

View file

@ -36,8 +36,8 @@ ReadManager::ReadManager(ref_ptr<ThreadsCommutator> commutator, MapDataProvider
, m_model(model)
, m_pool(make_unique_dp<threads::ThreadPool>(ReadCount(), bind(&ReadManager::OnTaskFinished, this, _1)))
, m_forceUpdate(true)
, m_is3d(false)
, m_is3dBuildings(false)
, m_need3dBuildings(false)
, m_allow3dBuildings(false)
, m_modeChanged(false)
, myPool(64, ReadMWMTaskFactory(m_memIndex, m_model))
, m_counter(0)
@ -73,14 +73,15 @@ void ReadManager::OnTaskFinished(threads::IRoutine * task)
myPool.Return(t);
}
void ReadManager::UpdateCoverage(ScreenBase const & screen, TTilesCollection const & tiles, ref_ptr<dp::TextureManager> texMng)
void ReadManager::UpdateCoverage(ScreenBase const & screen, bool is3dBuildings,
TTilesCollection const & tiles, ref_ptr<dp::TextureManager> texMng)
{
if (screen == m_currentViewport && !m_forceUpdate)
return;
m_forceUpdate = false;
m_is3d = screen.isPerspective();
m_modeChanged |= m_is3dBuildings && (m_is3d != m_currentViewport.isPerspective());
m_modeChanged |= m_need3dBuildings != is3dBuildings;
m_need3dBuildings = is3dBuildings;
if (m_modeChanged || MustDropAllTiles(screen))
{
@ -188,7 +189,7 @@ void ReadManager::PushTaskBackForTileKey(TileKey const & tileKey, ref_ptr<dp::Te
{
shared_ptr<TileInfo> tileInfo(new TileInfo(make_unique_dp<EngineContext>(TileKey(tileKey, m_generationCounter),
m_commutator, texMng)));
tileInfo->Set3dBuildings(m_is3d && m_is3dBuildings);
tileInfo->Set3dBuildings(m_need3dBuildings && m_allow3dBuildings);
m_tileInfos.insert(tileInfo);
ReadMWMTask * task = myPool.Get();
task->Init(tileInfo);
@ -197,7 +198,7 @@ void ReadManager::PushTaskBackForTileKey(TileKey const & tileKey, ref_ptr<dp::Te
void ReadManager::PushTaskFront(shared_ptr<TileInfo> const & tileToReread)
{
tileToReread->Set3dBuildings(m_is3d && m_is3dBuildings);
tileToReread->Set3dBuildings(m_need3dBuildings && m_allow3dBuildings);
ReadMWMTask * task = myPool.Get();
task->Init(tileToReread);
m_pool->PushFront(task);
@ -222,11 +223,11 @@ void ReadManager::IncreaseCounter(int value)
void ReadManager::Allow3dBuildings(bool allow3dBuildings)
{
if (m_is3dBuildings != allow3dBuildings)
if (m_allow3dBuildings != allow3dBuildings)
{
m_modeChanged = true;
m_forceUpdate = true;
m_is3dBuildings = allow3dBuildings;
m_allow3dBuildings = allow3dBuildings;
}
}

View file

@ -30,7 +30,7 @@ class ReadManager
public:
ReadManager(ref_ptr<ThreadsCommutator> commutator, MapDataProvider & model);
void UpdateCoverage(ScreenBase const & screen, TTilesCollection const & tiles,
void UpdateCoverage(ScreenBase const & screen, bool is3dBuildings, TTilesCollection const & tiles,
ref_ptr<dp::TextureManager> texMng);
void Invalidate(TTilesCollection const & keyStorage);
void Stop();
@ -57,8 +57,8 @@ private:
ScreenBase m_currentViewport;
bool m_forceUpdate;
bool m_is3d;
bool m_is3dBuildings;
bool m_need3dBuildings;
bool m_allow3dBuildings;
bool m_modeChanged;
struct LessByTileInfo

View file

@ -181,7 +181,8 @@ void RenderGroup::Disappear()
//else
{
// Create separate disappearing animation for area objects to eliminate flickering.
if (m_state.GetProgramIndex() == gpu::AREA_PROGRAM)
if (m_state.GetProgramIndex() == gpu::AREA_PROGRAM ||
m_state.GetProgramIndex() == gpu::AREA_3D_PROGRAM)
m_disappearAnimation = make_unique<OpacityAnimation>(0.01 /* duration */, 0.25 /* delay */,
1.0 /* startOpacity */, 1.0 /* endOpacity */);
}

View file

@ -3,11 +3,12 @@
namespace df
{
void RequestedTiles::Set(ScreenBase const & screen, TTilesCollection && tiles)
void RequestedTiles::Set(ScreenBase const & screen, bool is3dBuildings, TTilesCollection && tiles)
{
lock_guard<mutex> lock(m_mutex);
m_tiles = move(tiles);
m_screen = screen;
m_is3dBuildings = is3dBuildings;
}
TTilesCollection RequestedTiles::GetTiles()

View file

@ -13,14 +13,16 @@ class RequestedTiles
{
public:
RequestedTiles() = default;
void Set(ScreenBase const & screen, TTilesCollection && tiles);
void Set(ScreenBase const & screen, bool is3dBuildings, TTilesCollection && tiles);
TTilesCollection GetTiles();
ScreenBase GetScreen();
bool Is3dBuildings() const { return m_is3dBuildings; }
bool CheckTileKey(TileKey const & tileKey) const;
private:
TTilesCollection m_tiles;
ScreenBase m_screen;
bool m_is3dBuildings = false;
mutable mutex m_mutex;
};