AppFwk: Fix of Qt5 OpenGL related problems: Offset + Context deletion.

Added option to control the direction of the parallel projection headlight
Added optional visualization of point of interest to caf::Viewer
This commit is contained in:
Jacob Støren 2019-06-25 17:01:38 +02:00
parent 936d2e122d
commit 2930d41521
4 changed files with 136 additions and 7 deletions

View File

@ -30,6 +30,7 @@ add_library( ${PROJECT_NAME}
cafTrackBallBasedNavigation.h
cafNavigationPolicy.cpp
cafNavigationPolicy.h
cafPointOfInterestVisualizer.h
cafOpenGLWidget.cpp
cafOpenGLWidget.h
cafViewer.cpp

View File

@ -0,0 +1,62 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) CeetronSolutions AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cvfBase.h"
#include "cvfObject.h"
#include "cvfVector3.h"
namespace cvf
{
class Model;
}
namespace caf
{
class PointOfInterestVisualizer : public cvf::Object
{
public:
/// Returns the model containing the visualization of the PointOfInterest
/// Must always return the same model.
virtual cvf::Model* model() = 0;
/// Update the model to show a different point of interest position
virtual void update(cvf::Vec3d pointOfInterest) = 0;
};
}

View File

@ -34,12 +34,12 @@
//
//##################################################################################################
#include "cafViewer.h"
#include "cafCadNavigation.h"
#include "cafFrameAnimationControl.h"
#include "cafNavigationPolicy.h"
#include "cafPointOfInterestVisualizer.h"
#include "cvfCamera.h"
#include "cvfDebugTimer.h"
@ -112,7 +112,11 @@ cvf::ref<cvf::OpenGLContextGroup> caf::Viewer::sm_openGLContextGroup;
///
//--------------------------------------------------------------------------------------------------
caf::Viewer::Viewer(const QGLFormat& format, QWidget* parent)
#if QT_VERSION >= 0x050000
: caf::OpenGLWidget(contextGroup(), format, nullptr, sharedWidget()),
#else
: caf::OpenGLWidget(contextGroup(), format, new QWidget(parent), sharedWidget()),
#endif
m_navigationPolicy(nullptr),
m_navigationPolicyEnabled(true),
m_defaultPerspectiveNearPlaneDistance(0.05),
@ -122,10 +126,15 @@ caf::Viewer::Viewer(const QGLFormat& format, QWidget* parent)
m_releaseOGLResourcesEachFrame(false),
m_isOverlayPaintingEnabled(true),
m_offscreenViewportWidth(0),
m_offscreenViewportHeight(0)
m_offscreenViewportHeight(0),
m_parallelProjectionLightDirection(0, 0, -1) // Light directly from behind
{
#if QT_VERSION >= 0x050000
m_layoutWidget = new QWidget(parent);
#else
m_layoutWidget = parentWidget();
#endif
QHBoxLayout* layout = new QHBoxLayout(m_layoutWidget);
layout->addWidget(this);
@ -165,6 +174,7 @@ caf::Viewer::Viewer(const QGLFormat& format, QWidget* parent)
sm_viewers.push_back(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@ -419,6 +429,22 @@ void caf::Viewer::optimizeClippingPlanes()
//--------------------------------------------------------------------------------------------------
bool caf::Viewer::event(QEvent* e)
{
#if QT_VERSION >= 0x050000
// The most reliable way we have found of detecting when an OpenGL context is about to be destroyed is
// hooking into the QEvent::PlatformSurface event and checking for the SurfaceAboutToBeDestroyed event type.
// From the Qt doc:
// The underlying native surface will be destroyed immediately after this event.
// The SurfaceAboutToBeDestroyed event type is useful as a means of stopping rendering to a platform window before it is destroyed.
if ( e->type() == QEvent::PlatformSurface )
{
QPlatformSurfaceEvent* platformSurfaceEvent = static_cast<QPlatformSurfaceEvent*>(e);
if ( platformSurfaceEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed )
{
cvfShutdownOpenGLContext();
}
}
#endif
if (e && m_navigationPolicy.notNull() && m_navigationPolicyEnabled)
{
switch (e->type())
@ -618,10 +644,21 @@ void caf::Viewer::paintEvent(QPaintEvent* event)
optimizeClippingPlanes();
if ( m_poiVisualizationManager.notNull() )
{
m_poiVisualizationManager->update(m_navigationPolicy->pointOfInterest());
m_mainRendering->scene()->addModel(m_poiVisualizationManager->model());
}
// Do normal drawing
m_renderingSequence->render(myOglContext.p());
CVF_CHECK_OGL(cvfOpenGLContext());
if ( m_poiVisualizationManager.notNull() )
{
m_mainRendering->scene()->removeModel(m_poiVisualizationManager->model());
}
if (isShadersSupported())
{
cvfqt::OpenGLContext::restoreOpenGLState(myOglContext.p());
@ -1146,10 +1183,10 @@ void caf::Viewer::enableParallelProjection(bool enableOrtho)
m_mainCamera->setProjectionAsOrtho(1.0, m_mainCamera->nearPlane(), m_mainCamera->farPlane());
this->updateParallelProjectionHeightFromMoveZoom(pointOfInterest);
// Set the light position behind us, far away from the scene
// Set a fake directional light by putting the point far away from the scene
float sceneDepth = m_mainCamera->farPlane() - m_mainCamera->nearPlane();
this->m_renderingSequence->setDefaultFFLightPositional(cvf::Vec3f(0,0, 2 * sceneDepth));
m_globalUniformSet->setHeadLightPosition(cvf::Vec3f(0,0, 2 * sceneDepth));
this->m_renderingSequence->setDefaultFFLightPositional(-m_parallelProjectionLightDirection* 10*sceneDepth);
m_globalUniformSet->setHeadLightPosition(-m_parallelProjectionLightDirection* 10*sceneDepth);
this->update();
}
@ -1159,7 +1196,7 @@ void caf::Viewer::enableParallelProjection(bool enableOrtho)
// so we do not need to update the camera position based on orthoHeight and fieldOfView.
// We assume the camera is in a sensible position.
// Set dummy near and far plane. These wll be updated by the optimize clipping planes
// Set dummy near and far plane. These will be updated by the optimize clipping planes
m_mainCamera->setProjectionAsPerspective(m_cameraFieldOfViewYDeg, 0.1, 1.0);
this->m_renderingSequence->setDefaultFFLightPositional(cvf::Vec3f(0.5, 5.0, 7.0));
@ -1169,6 +1206,28 @@ void caf::Viewer::enableParallelProjection(bool enableOrtho)
}
}
//--------------------------------------------------------------------------------------------------
/// Direction in camera coordinates default is (0, 0, -1) directly from behind
//--------------------------------------------------------------------------------------------------
void caf::Viewer::setParallelProjectionHeadLightDirection(const cvf::Vec3f& direction)
{
m_parallelProjectionLightDirection = direction;
float sceneDepth = m_mainCamera->farPlane() - m_mainCamera->nearPlane();
this->m_renderingSequence->setDefaultFFLightPositional(-m_parallelProjectionLightDirection* 10*sceneDepth);
m_globalUniformSet->setHeadLightPosition(-m_parallelProjectionLightDirection* 10*sceneDepth);
this->update();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void caf::Viewer::setPointOfInterestVisualizer(PointOfInterestVisualizer* poiVisualizer)
{
m_poiVisualizationManager = poiVisualizer;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -65,6 +65,7 @@ namespace caf {
class FrameAnimationControl;
class NavigationPolicy;
class Viewer;
class PointOfInterestVisualizer;
}
class QInputEvent;
@ -121,6 +122,8 @@ public:
void setView( const cvf::Vec3d& alongDirection, const cvf::Vec3d& upDirection );
void zoomAll();
void enableParallelProjection(bool enable);
void setParallelProjectionHeadLightDirection(const cvf::Vec3f& direction);
void setPointOfInterestVisualizer(PointOfInterestVisualizer* poiVisualizer);
// Interface for navigation policies
void updateParallelProjectionHeightFromMoveZoom(const cvf::Vec3d& pointOfInterest);
@ -224,9 +227,13 @@ private:
cvf::Collection<cvf::Scene> m_frameScenes;
cvf::Collection<cvf::Model> m_staticModels;
// Poi visualization
cvf::ref<PointOfInterestVisualizer> m_poiVisualizationManager;
// Parallel projection light modification
cvf::ref<GlobalViewerDynUniformSet> m_globalUniformSet;
cvf::Vec3f m_parallelProjectionLightDirection;
// Offscreen render objects
cvf::ref<cvf::FramebufferObject> m_offscreenFbo;