diff --git a/CMakeLists.txt b/CMakeLists.txt index 1444f6dae1..c95c507f7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -681,6 +681,14 @@ if(CMAKE_COMPILER_IS_GNUCC) endif() +# !!! For now, we force Qt to version 5 +message(STATUS "Forcing setting of CEE_USE_QT5 to ON") +set(CEE_USE_QT5 + ON + CACHE BOOL "Force usage of Qt5" FORCE +) +message(STATUS "CEE_USE_QT5=${CEE_USE_QT5}") + add_subdirectory(${VIZ_MODULES_FOLDER_NAME}/LibCore) add_subdirectory(${VIZ_MODULES_FOLDER_NAME}/LibGeometry) add_subdirectory(${VIZ_MODULES_FOLDER_NAME}/LibRender) diff --git a/Fwk/AppFwk/cafViewer/cafOpenGLWidget.cpp b/Fwk/AppFwk/cafViewer/cafOpenGLWidget.cpp index c343eccc69..9105fae538 100644 --- a/Fwk/AppFwk/cafViewer/cafOpenGLWidget.cpp +++ b/Fwk/AppFwk/cafViewer/cafOpenGLWidget.cpp @@ -37,7 +37,7 @@ #include "cafOpenGLWidget.h" #include "cvfBase.h" #include "cvfOpenGLContextGroup.h" -#include "cvfqtCvfBoundQGLContext.h" +#include "cvfqtCvfBoundQGLContext_deprecated.h" namespace caf { @@ -58,22 +58,25 @@ OpenGLWidget::OpenGLWidget( cvf::OpenGLContextGroup* contextGroup, QWidget* parent, OpenGLWidget* shareWidget, Qt::WindowFlags f ) - : QGLWidget( new cvfqt::CvfBoundQGLContext( contextGroup, format ), parent, shareWidget, f ) + : QGLWidget( new cvfqt::CvfBoundQGLContext_deprecated( contextGroup, format ), parent, shareWidget, f ) { if ( isValid() ) { cvf::ref myContext = cvfOpenGLContext(); if ( myContext.notNull() ) { + cvf::OpenGLContextGroup* myOwnerContextGroup = myContext->group(); + if ( shareWidget ) { // We need to check if we actually got a context that shares resources with shareWidget. cvf::ref shareContext = shareWidget->cvfOpenGLContext(); + CVF_ASSERT( myOwnerContextGroup == shareContext->group() ); if ( isSharing() ) { - CVF_ASSERT( myContext->group() == shareContext->group() ); - myContext->initializeContext(); + makeCurrent(); + myOwnerContextGroup->initializeContextGroup( myContext.p() ); } else { @@ -81,13 +84,14 @@ OpenGLWidget::OpenGLWidget( cvf::OpenGLContextGroup* contextGroup, // since the construction process above has already optimistically added the new context to the // existing group. In this case, the newly context is basically defunct so we just shut it down // (which will also remove it from the group) - myContext->shutdownContext(); + myOwnerContextGroup->contextAboutToBeShutdown( myContext.p() ); CVF_ASSERT( myContext->group() == nullptr ); } } else { - myContext->initializeContext(); + makeCurrent(); + contextGroup->initializeContextGroup( myContext.p() ); } } } @@ -106,7 +110,7 @@ OpenGLWidget::OpenGLWidget( cvf::OpenGLContextGroup* contextGroup, /// If the context is not valid, sharing failed and the newly created widget/context be discarded. //-------------------------------------------------------------------------------------------------- OpenGLWidget::OpenGLWidget( OpenGLWidget* shareWidget, QWidget* parent, Qt::WindowFlags f ) - : QGLWidget( new cvfqt::CvfBoundQGLContext( shareWidget->cvfOpenGLContext()->group(), shareWidget->format() ), + : QGLWidget( new cvfqt::CvfBoundQGLContext_deprecated( shareWidget->cvfOpenGLContext()->group(), shareWidget->format() ), parent, shareWidget, f ) @@ -118,13 +122,16 @@ OpenGLWidget::OpenGLWidget( OpenGLWidget* shareWidget, QWidget* parent, Qt::Wind cvf::ref myContext = cvfOpenGLContext(); if ( myContext.notNull() ) { + cvf::OpenGLContextGroup* myOwnerContextGroup = myContext->group(); + // We need to check if we actually got a context that shares resources with shareWidget. if ( isSharing() ) { if ( isValid() ) { CVF_ASSERT( myContext->group() == shareContext->group() ); - myContext->initializeContext(); + makeCurrent(); + myOwnerContextGroup->initializeContextGroup( myContext.p() ); } } else @@ -133,7 +140,7 @@ OpenGLWidget::OpenGLWidget( OpenGLWidget* shareWidget, QWidget* parent, Qt::Wind // the construction process above has already optimistically added the new context to the existing group. // In this case, the newly context is basically defunct so we just shut it down (which will also remove it // from the group) - myContext->shutdownContext(); + myOwnerContextGroup->contextAboutToBeShutdown( myContext.p() ); CVF_ASSERT( myContext->group() == nullptr ); } } @@ -144,8 +151,9 @@ OpenGLWidget::OpenGLWidget( OpenGLWidget* shareWidget, QWidget* parent, Qt::Wind //-------------------------------------------------------------------------------------------------- cvf::OpenGLContext* OpenGLWidget::cvfOpenGLContext() const { - const QGLContext* qglContext = context(); - const cvfqt::CvfBoundQGLContext* contextBinding = dynamic_cast( qglContext ); + const QGLContext* qglContext = context(); + const cvfqt::CvfBoundQGLContext_deprecated* contextBinding = + dynamic_cast( qglContext ); CVF_ASSERT( contextBinding ); return contextBinding->cvfOpenGLContext(); @@ -161,7 +169,14 @@ void OpenGLWidget::cvfShutdownOpenGLContext() cvf::ref myContext = cvfOpenGLContext(); if ( myContext.notNull() ) { - myContext->shutdownContext(); + cvf::OpenGLContextGroup* myOwnerContextGroup = myContext->group(); + + // If shutdown has already been called, the context is no longer member of any group + if ( myOwnerContextGroup ) + { + makeCurrent(); + myOwnerContextGroup->contextAboutToBeShutdown( myContext.p() ); + } } } diff --git a/Fwk/AppFwk/cafViewer/cafViewer.cpp b/Fwk/AppFwk/cafViewer/cafViewer.cpp index d4bd7f2a27..22ae1b00ae 100644 --- a/Fwk/AppFwk/cafViewer/cafViewer.cpp +++ b/Fwk/AppFwk/cafViewer/cafViewer.cpp @@ -52,6 +52,7 @@ #include "cvfModel.h" #include "cvfOpenGLCapabilities.h" #include "cvfOpenGLResourceManager.h" +#include "cvfOpenGLUtils.h" #include "cvfOverlayImage.h" #include "cvfPart.h" #include "cvfRay.h" @@ -69,7 +70,6 @@ #include "cvfUniform.h" #include "cvfUniformSet.h" -#include "cvfqtOpenGLContext.h" #include "cvfqtPerformanceInfoHud.h" #include "cvfqtUtils.h" @@ -850,7 +850,7 @@ void caf::Viewer::paintEvent( QPaintEvent* event ) if ( isShadersSupported() ) { - cvfqt::OpenGLContext::saveOpenGLState( myOglContext.p() ); + cvf::OpenGLUtils::pushOpenGLState( myOglContext.p() ); } optimizeClippingPlanes(); @@ -880,7 +880,7 @@ void caf::Viewer::paintEvent( QPaintEvent* event ) if ( isShadersSupported() ) { - cvfqt::OpenGLContext::restoreOpenGLState( myOglContext.p() ); + cvf::OpenGLUtils::popOpenGLState( myOglContext.p() ); } painter.endNativePainting(); diff --git a/Fwk/VizFwk/CMakeLists.txt b/Fwk/VizFwk/CMakeLists.txt index 1d813987d9..dd046624ac 100644 --- a/Fwk/VizFwk/CMakeLists.txt +++ b/Fwk/VizFwk/CMakeLists.txt @@ -3,6 +3,13 @@ cmake_minimum_required(VERSION 3.15) project(VizFramework) +if (CEE_CEEVIZ_ROOT) + message(STATUS "CEE_CEEVIZ_ROOT: ${CEE_CEEVIZ_ROOT}") +else() + set(CEE_CEEVIZ_ROOT ${PROJECT_SOURCE_DIR}) + message(STATUS "Setting CEE_CEEVIZ_ROOT to ${CEE_CEEVIZ_ROOT}") +endif() + # Determine if we're being run stand-alone or invoked from some other project set(CEE_STAND_ALONE ON) if (PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) @@ -20,6 +27,8 @@ if (CEE_STAND_ALONE) endif() include(CMake/Utils/ceeDetermineCompilerFlags.cmake) + + set(CMAKE_CXX_STANDARD 17) endif() @@ -44,36 +53,46 @@ add_subdirectory(ThirdParty/FreeType) add_subdirectory(LibUtilities) - option(CEE_BUILD_GUI_QT "Build GUI library for Qt" ON) if (CEE_BUILD_GUI_QT) - option(CEE_USE_QT5 "Use Qt5" ON) + option(CEE_USE_QT6 "Use Qt6" OFF) + option(CEE_USE_QT5 "Use Qt5" OFF) add_subdirectory(LibGuiQt) endif() if (CEE_STAND_ALONE) - option(CEE_BUILD_UNIT_TESTS "Build unit tests" ON) - if (CEE_BUILD_UNIT_TESTS) - add_subdirectory(Tests) - endif() + option(CEE_BUILD_TEST_APPS "Build test apps" ON) +endif() +if (CEE_BUILD_UNIT_TESTS OR CEE_BUILD_TEST_APPS) + # Add CeeViz's root source dir as a preprocessor directive so unit tests and test apps can determine where to find the resources they want. + add_definitions(-DCVF_CEEVIZ_ROOT_SOURCE_DIR="${CEE_CEEVIZ_ROOT}") +endif() - option(CEE_BUILD_TEST_APPS "Build test apps" ON) - if (CEE_BUILD_TEST_APPS) - # For now, build the snippet libs here - add_subdirectory(Tests/SnippetsBasis) - - if (CEE_BUILD_GUI_QT) - add_subdirectory(TestApps/Qt/QtMinimal) - add_subdirectory(TestApps/Qt/QtMultiView) - add_subdirectory(TestApps/Qt/QtSnippetRunner) - endif() +if (CEE_BUILD_UNIT_TESTS) + add_subdirectory(Tests) +endif() - if (WIN32) - add_subdirectory(TestApps/Win32/Win32SnippetRunner) +if (CEE_BUILD_TEST_APPS) + # For now, build the snippet libs here + add_subdirectory(Tests/SnippetsBasis) + + if (CEE_BUILD_GUI_QT) + add_subdirectory(TestApps/Qt/QtMinimal) + add_subdirectory(TestApps/Qt/QtMultiView) + add_subdirectory(TestApps/Qt/QtTestBenchOpenGLWidget) + add_subdirectory(TestApps/Qt/QtSnippetRunner) + + if (CEE_USE_QT5) + add_subdirectory(TestApps/Qt/QtMinimal_GLWidget) + add_subdirectory(TestApps/Qt/QtMinimal_deprecated) + add_subdirectory(TestApps/Qt/QtMultiView_deprecated) endif() endif() + if (WIN32) + add_subdirectory(TestApps/Win32/Win32SnippetRunner) + endif() endif() diff --git a/Fwk/VizFwk/LibCore/CMakeLists.txt b/Fwk/VizFwk/LibCore/CMakeLists.txt index b08f9f82bf..517acbf9e9 100644 --- a/Fwk/VizFwk/LibCore/CMakeLists.txt +++ b/Fwk/VizFwk/LibCore/CMakeLists.txt @@ -112,5 +112,11 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR} ) +if (UNIX AND NOT APPLE) + # Our core library has dependencies on librt and libpthread for timers and mutex. + target_link_libraries(${PROJECT_NAME} -lrt -lpthread) +endif() + + set(PROJECT_FILES ${CEE_HEADER_FILES} ${CEE_SOURCE_FILES}) source_group("" FILES ${PROJECT_FILES}) diff --git a/Fwk/VizFwk/LibCore/cvfBase.h b/Fwk/VizFwk/LibCore/cvfBase.h index 6b6e8bf6e6..9944b8380e 100644 --- a/Fwk/VizFwk/LibCore/cvfBase.h +++ b/Fwk/VizFwk/LibCore/cvfBase.h @@ -68,7 +68,7 @@ // Makes it easier to check on the current GCC version #ifdef __GNUC__ // 40302 means version 4.3.2. -# define CVF_GCC_VER (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) +#define CVF_GCC_VER (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__) #endif // Helper macro to disable (ignore) compiler warnings on GCC @@ -80,6 +80,15 @@ #define CVF_GCC_DIAGNOSTIC_IGNORE(OPTION_STRING) #endif +// Helper macros for push/pop of GCC diagnostics, available from GCC 4.6.x +#if defined(__GNUC__) && (CVF_GCC_VER >= 40600) +#define CVF_GCC_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") +#define CVF_GCC_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#else +#define CVF_GCC_DIAGNOSTIC_PUSH +#define CVF_GCC_DIAGNOSTIC_POP +#endif + #if defined(CVF_LINUX) || defined(CVF_IOS) || defined(CVF_OSX) || defined(CVF_ANDROID) // Used by int64_t on *nix below @@ -123,6 +132,13 @@ typedef __int64 int64; typedef int64_t int64; #endif +// 64bit unsigned integer support via the int64 type +#ifdef WIN32 +typedef unsigned __int64 uint64; +#elif defined(CVF_LINUX) || defined(CVF_IOS) || defined(CVF_OSX) || defined(CVF_ANDROID) +typedef uint64_t uint64; +#endif + } #include "cvfConfigCore.h" diff --git a/Fwk/VizFwk/LibCore/cvfLibCore.h b/Fwk/VizFwk/LibCore/cvfLibCore.h index 88238dfa22..850ba4f7c4 100644 --- a/Fwk/VizFwk/LibCore/cvfLibCore.h +++ b/Fwk/VizFwk/LibCore/cvfLibCore.h @@ -57,6 +57,7 @@ #include "cvfFlags.h" #include "cvfFunctorRange.h" #include "cvfLogger.h" +#include "cvfLogManager.h" #include "cvfMath.h" #include "cvfMatrix4.h" #include "cvfObject.h" diff --git a/Fwk/VizFwk/LibGeometry/CMakeLists.txt b/Fwk/VizFwk/LibGeometry/CMakeLists.txt index 00c9018dd8..dd6a5b49aa 100644 --- a/Fwk/VizFwk/LibGeometry/CMakeLists.txt +++ b/Fwk/VizFwk/LibGeometry/CMakeLists.txt @@ -9,6 +9,11 @@ endif() # Use our strict compile flags set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STRICT_CXX_FLAGS}") +# For now, disable warning about unknown pragmas locally here (due to usage of OpenMP) +if (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unknown-pragmas") +endif() + set(CEE_HEADER_FILES cvfArrowGenerator.h diff --git a/Fwk/VizFwk/LibGuiQt/CMakeLists.txt b/Fwk/VizFwk/LibGuiQt/CMakeLists.txt index f0c5385f35..dfe208df6f 100644 --- a/Fwk/VizFwk/LibGuiQt/CMakeLists.txt +++ b/Fwk/VizFwk/LibGuiQt/CMakeLists.txt @@ -10,19 +10,31 @@ endif() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_BASE_CXX_FLAGS}") if (CMAKE_COMPILER_IS_GNUCXX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long") + # Due to usage of OpenMP, disable warning about unknown pragmas + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long -Wno-unknown-pragmas") endif() find_package(OpenGL) -find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) -set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) + +message(STATUS "In LibGuiQt, CEE_USE_QT6=${CEE_USE_QT6}") +message(STATUS "In LibGuiQt, CEE_USE_QT5=${CEE_USE_QT5}") +if (CEE_USE_QT6) + find_package(Qt6 COMPONENTS REQUIRED Core Gui Widgets OpenGLWidgets) + set(QT_LIBRARIES Qt6::Core Qt6::Gui Qt6::Widgets Qt6::OpenGLWidgets ) +elseif (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) +else() + message(FATAL_ERROR "No supported Qt version selected for build") +endif() + + + set(CEE_HEADER_FILES cvfqtBasicAboutDialog.h -cvfqtCvfBoundQGLContext.h cvfqtMouseState.h -cvfqtOpenGLContext.h cvfqtOpenGLWidget.h cvfqtPerformanceInfoHud.h cvfqtUtils.h @@ -30,14 +42,21 @@ cvfqtUtils.h set(CEE_SOURCE_FILES cvfqtBasicAboutDialog.cpp -cvfqtCvfBoundQGLContext.cpp cvfqtMouseState.cpp -cvfqtOpenGLContext.cpp cvfqtOpenGLWidget.cpp cvfqtPerformanceInfoHud.cpp cvfqtUtils.cpp ) +if (CEE_USE_QT5) + set(CEE_HEADER_FILES ${CEE_HEADER_FILES} cvfqtGLWidget.h) + set(CEE_SOURCE_FILES ${CEE_SOURCE_FILES} cvfqtGLWidget.cpp) + set(CEE_HEADER_FILES ${CEE_HEADER_FILES} cvfqtCvfBoundQGLContext_deprecated.h) + set(CEE_SOURCE_FILES ${CEE_SOURCE_FILES} cvfqtCvfBoundQGLContext_deprecated.cpp) + set(CEE_HEADER_FILES ${CEE_HEADER_FILES} cvfqtGLWidget_deprecated.h) + set(CEE_SOURCE_FILES ${CEE_SOURCE_FILES} cvfqtGLWidget_deprecated.cpp) +endif() + add_library(${PROJECT_NAME} ${CEE_HEADER_FILES} ${CEE_SOURCE_FILES}) target_include_directories(${PROJECT_NAME} @@ -58,6 +77,5 @@ source_group("" FILES ${PROJECT_FILES}) # Unity Build if (CMAKE_UNITY_BUILD) - set_source_files_properties (cvfqtOpenGLWidget.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE) - set_source_files_properties (cvfqtOpenGLContext.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE) + set_source_files_properties (cvfqtGLWidget_deprecated.cpp PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE) endif() diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtBasicAboutDialog.cpp b/Fwk/VizFwk/LibGuiQt/cvfqtBasicAboutDialog.cpp index af6fddd284..21d9ee74da 100644 --- a/Fwk/VizFwk/LibGuiQt/cvfqtBasicAboutDialog.cpp +++ b/Fwk/VizFwk/LibGuiQt/cvfqtBasicAboutDialog.cpp @@ -255,8 +255,7 @@ void BasicAboutDialog::create() // Library version if (m_showLibraryVersion) { - QString ver; - ver.sprintf("%s.%s%s-%s", CVF_MAJOR_VERSION, CVF_MINOR_VERSION, CVF_SPECIAL_BUILD, CVF_BUILD_NUMBER); + QString ver = QString("%1.%2%3-%4").arg(CVF_MAJOR_VERSION).arg(CVF_MINOR_VERSION).arg(CVF_SPECIAL_BUILD).arg(CVF_BUILD_NUMBER); addStringPairToVerInfoLayout("Library ver.: ", ver, verInfoLayout, insertRow++); } diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext_deprecated.cpp b/Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext_deprecated.cpp new file mode 100644 index 0000000000..78a67e2fac --- /dev/null +++ b/Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext_deprecated.cpp @@ -0,0 +1,150 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#include "cvfBase.h" +#include "cvfOpenGLCapabilities.h" +#include "cvfqtCvfBoundQGLContext_deprecated.h" + +namespace cvfqt { + + + +//================================================================================================== +/// +/// \class cvfqt::OpenGLContext_QGLContextAdapter_deprecated +/// \ingroup GuiQt +/// +/// Derived OpenGLContext that adapts a Qt QGLContext +/// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +OpenGLContext_QGLContextAdapter_deprecated::OpenGLContext_QGLContextAdapter_deprecated(cvf::OpenGLContextGroup* contextGroup, QGLContext* backingQGLContext) +: cvf::OpenGLContext(contextGroup) +{ + m_qtGLContext = backingQGLContext; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +OpenGLContext_QGLContextAdapter_deprecated::~OpenGLContext_QGLContextAdapter_deprecated() +{ + m_qtGLContext = NULL; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void OpenGLContext_QGLContextAdapter_deprecated::makeCurrent() +{ + CVF_ASSERT(m_qtGLContext); + m_qtGLContext->makeCurrent(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool OpenGLContext_QGLContextAdapter_deprecated::isCurrent() const +{ + if (m_qtGLContext) + { + if (QGLContext::currentContext() == m_qtGLContext) + { + return true; + } + } + + return false; +} + + + + +//================================================================================================== +/// +/// \class cvfqt::CvfBoundQGLContext_deprecated +/// \ingroup GuiQt +/// +/// +/// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +CvfBoundQGLContext_deprecated::CvfBoundQGLContext_deprecated(cvf::OpenGLContextGroup* contextGroup, const QGLFormat & format) +: QGLContext(format) +{ + m_cvfGLContext = new OpenGLContext_QGLContextAdapter_deprecated(contextGroup, this); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +CvfBoundQGLContext_deprecated::~CvfBoundQGLContext_deprecated() +{ + if (m_cvfGLContext.notNull()) + { + // TODO + // Need to resolve the case where the Qt QGLcontext (that we're deriving from) is deleted + // and we are still holding a reference to one or more OpenGLContext objects + // By the time we get here we expect that we're holding the only reference + CVF_ASSERT(m_cvfGLContext->refCount() == 1); + m_cvfGLContext = NULL; + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::OpenGLContext* CvfBoundQGLContext_deprecated::cvfOpenGLContext() const +{ + return const_cast(m_cvfGLContext.p()); +} + + +} // namespace cvfqt + + diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext_deprecated.h b/Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext_deprecated.h new file mode 100644 index 0000000000..7bc173973a --- /dev/null +++ b/Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext_deprecated.h @@ -0,0 +1,84 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#pragma once + +#include "cvfOpenGLContext.h" + +#include + +namespace cvfqt { + + +//================================================================================================== +// +// Derived OpenGLContext that adapts a Qt QGLContext +// +//================================================================================================== +class OpenGLContext_QGLContextAdapter_deprecated : public cvf::OpenGLContext +{ +public: + OpenGLContext_QGLContextAdapter_deprecated(cvf::OpenGLContextGroup* contextGroup, QGLContext* backingQGLContext); + virtual ~OpenGLContext_QGLContextAdapter_deprecated(); + + virtual void makeCurrent(); + virtual bool isCurrent() const; + +private: + QGLContext* m_qtGLContext; +}; + + + +//================================================================================================== +// +// Utility class used to piggyback OpenGLContext onto Qt's QGLContext +// +//================================================================================================== +class CvfBoundQGLContext_deprecated : public QGLContext +{ +public: + CvfBoundQGLContext_deprecated(cvf::OpenGLContextGroup* contextGroup, const QGLFormat & format); + virtual ~CvfBoundQGLContext_deprecated(); + + cvf::OpenGLContext* cvfOpenGLContext() const; + +private: + cvf::ref m_cvfGLContext; +}; + +} diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget.cpp b/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget.cpp new file mode 100644 index 0000000000..cc211f921f --- /dev/null +++ b/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget.cpp @@ -0,0 +1,518 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#include "cvfqtGLWidget.h" + +#include "cvfOpenGLContextGroup.h" +#include "cvfOpenGLContext.h" +#include "cvfLogManager.h" +#include "cvfTrace.h" + +#include +#include +#include +#include + +namespace cvfqt { + + + +//================================================================================================== +// +// +// +//================================================================================================== +class ForwardingOpenGLContext_GLWidget : public cvf::OpenGLContext +{ +public: + ForwardingOpenGLContext_GLWidget(cvf::OpenGLContextGroup* contextGroup, QGLWidget* ownerQtGLWidget) + : cvf::OpenGLContext(contextGroup), + m_ownerQtGLWidget(ownerQtGLWidget) + { + CVF_ASSERT(contextGroup); + + // In our current usage pattern the owner widget (and its contained Qt OpenGL context) must already be initialized/created + CVF_ASSERT(m_ownerQtGLWidget); + CVF_ASSERT(m_ownerQtGLWidget->isValid()); + CVF_ASSERT(m_ownerQtGLWidget->context()); + CVF_ASSERT(m_ownerQtGLWidget->context()->isValid()); + } + + virtual void makeCurrent() + { + if (m_ownerQtGLWidget) + { + m_ownerQtGLWidget->makeCurrent(); + } + } + + virtual bool isCurrent() const + { + const QGLContext* ownersQGLContext = m_ownerQtGLWidget ? m_ownerQtGLWidget->context() : NULL; + if (ownersQGLContext && QGLContext::currentContext() == ownersQGLContext) + { + return true; + } + + return false; + } + + virtual cvf::OglId defaultFramebufferObject() const + { + if (m_ownerQtGLWidget) + { + const QGLContext* ownersQGLContext = m_ownerQtGLWidget->context(); + const QOpenGLContext* ownersQOpenGLContext = ownersQGLContext ? ownersQGLContext->contextHandle() : NULL; + return ownersQOpenGLContext ? ownersQOpenGLContext->defaultFramebufferObject() : 0; + } + + return 0; + } + +private: + QPointer m_ownerQtGLWidget; +}; + + + + +//================================================================================================== +/// +/// \class cvfqt::GLWidget +/// \ingroup GuiQt +/// +/// +/// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// Constructor, use this for the first or only widget in your application. +//-------------------------------------------------------------------------------------------------- +GLWidget::GLWidget(cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent, Qt::WindowFlags f) +: QGLWidget(format, parent, NULL, f), + m_cvfOpenGLContextGroup(contextGroup), + m_logger(CVF_GET_LOGGER("cee.cvf.qt")) +{ + // Must pass a context group + CVF_ASSERT(m_cvfOpenGLContextGroup.notNull()); + + // Only the first widget in a context group can be created using this constructor + // All following widgets must be created using the constructor overload that takes a shareWidget + CVF_ASSERT(m_cvfOpenGLContextGroup->contextCount() == 0); + + // The isValid() call will return true if the widget has a valid GL rendering context; otherwise returns false. + // The widget will be invalid if the system has no OpenGL support. + if (!isValid()) + { + CVF_LOG_ERROR(m_logger, "Widget creation failed, the system has no OpenGL support"); + return; + } + + + // The Qt docs for QGLWidget and all previous experience indicates that it is OK to do OpenGL related + // initialization in QGLWidget's constructor (contrary to QOpenGLWidget). + // Note that the Qt docs still hint that initialization should be deferred to initializeGL(). If we ever + // experience problems related to doing initialization here, we should probably move the initialization. + + // Since we're in the constructor we must ensure this widget's context is current before initialization + makeCurrent(); + + const QGLContext* myQtGLContext = context(); + CVF_ASSERT(myQtGLContext); + CVF_ASSERT(myQtGLContext->isValid()); + CVF_ASSERT(QGLContext::currentContext() == myQtGLContext); + + m_cvfForwardingOpenGLContext = new ForwardingOpenGLContext_GLWidget(m_cvfOpenGLContextGroup.p(), this); + + if (!m_cvfOpenGLContextGroup->initializeContextGroup(m_cvfForwardingOpenGLContext.p())) + { + CVF_LOG_ERROR(m_logger, "Error initializing context group"); + } + + + // Install our event filter + installEventFilter(this); + + // If we're using Qt5 or above, we can get hold of a QOpenGLContext from our QGLContext + // Connect to QOpenGLContext's aboutToBeDestroyed signal so we get notified when Qt's OpenGL context is about to be destroyed + connect(myQtGLContext->contextHandle(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::qtOpenGLContextAboutToBeDestroyed); +} + + +//-------------------------------------------------------------------------------------------------- +/// Constructor, creates a widget sharing the OpenGL resources with the specified widget. +//-------------------------------------------------------------------------------------------------- +GLWidget::GLWidget(GLWidget* shareWidget, QWidget* parent , Qt::WindowFlags f) +: QGLWidget(shareWidget->context()->requestedFormat(), parent, shareWidget, f), + m_logger(CVF_GET_LOGGER("cee.cvf.qt")) +{ + // Note that when calling QGLWidget's constructor in the initializer list above, we *must* use the + // constructor overload that takes a format as its first parameter. If we do not do this, the default QGLFormat + // will be used, and it may not be compatible with the format of the shareWidget. + // We grab hold of the format from the shareWidget, but note that we do that by calling requestedFormat() + // instead of just format() to ensure that the format being requested here is the same as the one that was actually used + // in the "first widget constructor" and not whatever format the first widget ended up with after construction. + + // Requires that a share widget is passed in as parameter + CVF_ASSERT(shareWidget); + + // If the share widget doesn't have a CVF OpenGL context something went wrong when it was created and we cannot continue + cvf::ref shareContext = shareWidget->cvfOpenGLContext(); + CVF_ASSERT(shareContext.notNull()); + + if (!isValid()) + { + CVF_LOG_ERROR(m_logger, "Widget creation failed, the system has no OpenGL support"); + return; + } + + // We need to check if we actually got a context that shares resources with the passed shareWidget. + if (!isSharing()) + { + CVF_LOG_ERROR(m_logger, "Widget creation failed, unable to create a shared OpenGL context"); + return; + } + + + // Since we're in the constructor we must ensure this widget's context is current before initialization + makeCurrent(); + + const QGLContext* myQtGLContext = context(); + CVF_ASSERT(myQtGLContext); + CVF_ASSERT(myQtGLContext->isValid()); + CVF_ASSERT(QGLContext::currentContext() == myQtGLContext); + + m_cvfOpenGLContextGroup = shareContext->group(); + CVF_ASSERT(m_cvfOpenGLContextGroup.notNull()); + + m_cvfForwardingOpenGLContext = new ForwardingOpenGLContext_GLWidget(m_cvfOpenGLContextGroup.p(), this); + + // Normally, the context group should already be initialized when the first widget in the group was created. + // Still, for good measure do an initialization here. It will amount to a no-op if context group is already initialized + if (!m_cvfOpenGLContextGroup->initializeContextGroup(m_cvfForwardingOpenGLContext.p())) + { + CVF_LOG_ERROR(m_logger, "Error initializing context group using sharing widget"); + } + + + // Install our event filter + installEventFilter(this); + + // If we're using Qt5 or above, we can get hold of a QOpenGLContext from our QGLContext + // Connect to QOpenGLContext's aboutToBeDestroyed signal so we get notified when Qt's OpenGL context is about to be destroyed + connect(myQtGLContext->contextHandle(), &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::qtOpenGLContextAboutToBeDestroyed); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +GLWidget::~GLWidget() +{ + cvf::Trace::show("GLWidget::~GLWidget()"); + + // Make sure we disconnect from the aboutToBeDestroyed signal since after this destructor has been + // called, out object is dangling and the call to the slot will cause a crash + const QGLContext* myQtGLContext = context(); + const QOpenGLContext* myQtOpenGLContext = myQtGLContext ? myQtGLContext->contextHandle() : NULL; + if (myQtOpenGLContext) + { + disconnect(myQtOpenGLContext, &QOpenGLContext::aboutToBeDestroyed, this, &GLWidget::qtOpenGLContextAboutToBeDestroyed); + } + + // For Qt5, our testing indicates that once we hit the widget's destructor it may be too late + // to try and do any cleanup of OpenGL resources. Most of the time it works, but typically it will fail when + // we're shutting down the application by closing the main window. In such cases it seems that the OpenGL + // context cannot be made current anymore. + // + // One solution to this is to do an explicit shutdown of the context while before the system + // start shutting down. One traditional way of doing this is to iterate over all GLWidgets and call + // the cvfShutdownOpenGLContext() explicitly, eg from QMainWindow::closeEvent() + // + // In our quest to get a notification just before the QGLContext dies we have also tried to go via + // QGLContext's QOpenGLContext and connect to the aboutToBeDestroyed signal. This signal does indeed trigger + // before the QGLContext dies, but it seems that at this point we are no longer able to make the context + // current which is a requirement before we can do our OpenGL related cleanup. + // + // Another promising solution that seems to work reliably is to install an event filter and respond to + // the QEvent::PlatformSurface event. See our eventFilter() override + + // For Qt4 it seems that doing OpenGL related cleanup in the destructor is OK + // We're able to make the context current and delete any OpenGL resources necessary through the cvfShutdownOpenGLContext(); + + + // Note that calling this function is safe even if the context has already been shut down. + // It may however fail/assert if the context hasn't already been shut down and if we're unable to make the OpenGL context current + cvfShutdownOpenGLContext(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::OpenGLContext* GLWidget::cvfOpenGLContext() +{ + return m_cvfForwardingOpenGLContext.p(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void GLWidget::cvfShutdownOpenGLContext() +{ + if (m_cvfForwardingOpenGLContext.notNull()) + { + makeCurrent(); + + // If we're not able to make the context current, the eventual un-initialize that will happen + // in the context group when we remove the last context will fail. + const QGLContext* myContext = context(); + const QGLContext* currContext = QGLContext::currentContext(); + if (myContext != currContext) + { + CVF_LOG_WARNING(m_logger, "Could not make the widget's OpenGL context current for context shutdown"); + } + + m_cvfOpenGLContextGroup->contextAboutToBeShutdown(m_cvfForwardingOpenGLContext.p()); + m_cvfForwardingOpenGLContext = NULL; + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void GLWidget::initializeGL() +{ + //cvf::Trace::show("GLWidget::initializeGL()"); + + // According to Qt doc this function is called once before the first call to paintGL() or resizeGL(), + // and then once whenever the widget has been assigned a new QGLContext. There is no need to call makeCurrent() because + // this has already been done when this function is called. + + if (m_cvfForwardingOpenGLContext.isNull()) + { + CVF_LOG_ERROR(m_logger, "Unexpected error in GLWidget::initializeGL(), no forwarding OpenGL context present"); + return; + } + + // Initialization of context group should already be done, but for good measure + CVF_ASSERT(m_cvfOpenGLContextGroup.notNull()); + if (!m_cvfOpenGLContextGroup->isContextGroupInitialized()) + { + CVF_LOG_DEBUG(m_logger, "Doing late initialization of context group in GLWidget::initializeGL()"); + if (!m_cvfOpenGLContextGroup->initializeContextGroup(m_cvfForwardingOpenGLContext.p())) + { + CVF_LOG_ERROR(m_logger, "Initialization of context group in GLWidget::initializeGL() failed"); + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void GLWidget::resizeGL(int /*width*/, int /*height*/) +{ + // Intentionally empty, and no implementation in QGLWidget::resizeGL() either. + // Should normally be implemented in derived class +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void GLWidget::paintGL() +{ + // No implementation here and no significant implementation in QGLWidget either. + // In Qt4 QGLWidget::paintGL() does nothing. In Qt5 QGLWidget::paintGL() merely clears the depth and color buffer. + // Derived classes must reimplement this function in order to do painting. +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void GLWidget::qtOpenGLContextAboutToBeDestroyed() +{ + //cvf::Trace::show("GLWidget::qtOpenGLContextAboutToBeDestroyed()"); + + cvfShutdownOpenGLContext(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool GLWidget::eventFilter(QObject* watched, QEvent* event) +{ + // 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 (event->type() == QEvent::PlatformSurface) + { + QPlatformSurfaceEvent* platformSurfaceEvent = static_cast(event); + if (platformSurfaceEvent->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) + { + CVF_LOG_DEBUG(m_logger, "Shutting down OpenGL context in response to platform surface about to be destroyed"); + cvfShutdownOpenGLContext(); + } + } + + // Reading the Qt docs it can seem like reparenting of the QGLWidget might pose a problem for us. + // According to the doc, a change of parent will cause the widget's QGLContext to be deleted and a new one + // to be created. In Qt4, this does indeed seem to happen, whereas for Qt5 it does not. Still, it appears that Qt4 makes + // an effort to make the new QGLContext compatible with the old one, and does some tricks to set up temporary OpenGL + // resource sharing so that we may not actually be affected by this since we're actually not storing any references to + // the QGLContext, but accessing it indirectly through the widget in our ForwardingOpenGLContext. + // May also want to look out for + if (event->type() == QEvent::ParentChange) + { + CVF_LOG_DEBUG(m_logger, "cvfqt::GLWidget has been reparented. This may cause OpenGL issues"); + } + else if (event->type() == QEvent::ParentAboutToChange) + { + CVF_LOG_DEBUG(m_logger, "cvfqt::GLWidget is about to change parent. This may cause OpenGL issues"); + } + + return QGLWidget::eventFilter(watched, event); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void GLWidget::logOpenGLInfo() +{ + CVF_LOG_INFO(m_logger, "Starting logging of OpenGL info (cvfqt::GLWidget)..."); + + cvf::String sQtVerInfo = cvf::String("Qt version: %1 (run-time=%2)").arg(QT_VERSION_STR).arg(qVersion()); + CVF_LOG_INFO(m_logger, sQtVerInfo); + + if (!context() || !isValid()) + { + CVF_LOG_WARNING(m_logger, "QGLWidget does not have a valid GL rendering context, reported info will not be correct!"); + } + + // Log output from querying Qt + CVF_LOG_INFO(m_logger, "Qt OpenGL format info:"); + + const QGLFormat qglFormat = format(); + const QGLFormat::OpenGLContextProfile profile = qglFormat.profile(); + const QGLFormat::OpenGLVersionFlags qglVersionFlags = QGLFormat::openGLVersionFlags(); + + cvf::String sInfo = cvf::String(" info: version %1.%2, depthSize: %3, software: %4, doubleBuffer: %5, sampleBuffers: %6 (size: %7)") + .arg(qglFormat.majorVersion()).arg(qglFormat.minorVersion()) + .arg(qglFormat.depthBufferSize()) + .arg(qglFormat.directRendering() ? "no" : "yes") + .arg(qglFormat.doubleBuffer() ? "yes" : "no") + .arg(qglFormat.sampleBuffers() ? "yes" : "no") + .arg(qglFormat.samples()); + CVF_LOG_INFO(m_logger, sInfo); + + cvf::String sProfile = "UNKNOWN"; + if (profile == QGLFormat::NoProfile) sProfile = "NoProfile"; + else if (profile == QGLFormat::CoreProfile) sProfile = "CoreProfile"; + else if (profile == QGLFormat::CompatibilityProfile) sProfile = "CompatibilityProfile"; + CVF_LOG_INFO(m_logger, " context profile: " + sProfile); + + cvf::String sVersionsPresent = cvf::String(" versions present: 1.1: %1, 2.0: %2, 2.1: %3, 3.0: %4, 3.3: %5, 4.0: %6, ES2: %7") + .arg(qglVersionFlags & QGLFormat::OpenGL_Version_1_1 ? "yes" : "no") + .arg(qglVersionFlags & QGLFormat::OpenGL_Version_2_0 ? "yes" : "no") + .arg(qglVersionFlags & QGLFormat::OpenGL_Version_2_1 ? "yes" : "no") + .arg(qglVersionFlags & QGLFormat::OpenGL_Version_3_0 ? "yes" : "no") + .arg(qglVersionFlags & QGLFormat::OpenGL_Version_3_3 ? "yes" : "no") + .arg(qglVersionFlags & QGLFormat::OpenGL_Version_4_0 ? "yes" : "no") + .arg(qglVersionFlags & QGLFormat::OpenGL_ES_Version_2_0 ? "yes" : "no"); + CVF_LOG_INFO(m_logger, sVersionsPresent); + + CVF_LOG_INFO(m_logger, " is sharing: " + cvf::String(isSharing() ? "yes" : "no")); + + + // Log the information we have gathered when initializing the context group + const cvf::OpenGLInfo oglInfo = m_cvfOpenGLContextGroup->info(); + CVF_LOG_INFO(m_logger, "OpenGL info:"); + CVF_LOG_INFO(m_logger, " version: " + oglInfo.version()); + CVF_LOG_INFO(m_logger, " vendor: " + oglInfo.vendor()); + CVF_LOG_INFO(m_logger, " renderer: " + oglInfo.renderer()); + + + // Lastly, query OpenGL implementation directly if this context is current + GLint smoothLineWidthRange[2] = { -1, -1 }; + GLint smoothPointSizeRange[2] = { -1, -1 }; + GLint aliasedLineWidthRange[2] = { -1, -1 }; + GLint aliasedPointSizeRange[2] = { -1, -1 }; + + // Note that GL_LINE_WIDTH_RANGE and GL_SMOOTH_LINE_WIDTH_RANGE are synonyms (0x0B22) + // Likewise for GL_POINT_SIZE_RANGE and GL_SMOOTH_POINT_SIZE_RANGE are synonyms (0x0B12) +#ifndef GL_ALIASED_LINE_WIDTH_RANGE + #define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#endif +#ifndef GL_ALIASED_POINT_SIZE_RANGE + #define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#endif + + const bool thisContextIsCurrent = context() == QGLContext::currentContext(); + if (thisContextIsCurrent) + { + glGetIntegerv(GL_LINE_WIDTH_RANGE, smoothLineWidthRange); + glGetIntegerv(GL_POINT_SIZE_RANGE, smoothPointSizeRange); + if (qglVersionFlags & QGLFormat::OpenGL_Version_1_2) + { + glGetIntegerv(GL_ALIASED_LINE_WIDTH_RANGE, aliasedLineWidthRange); + glGetIntegerv(GL_ALIASED_POINT_SIZE_RANGE, aliasedPointSizeRange); + } + } + else + { + CVF_LOG_WARNING(m_logger, "Cannot query OpenGL directly, QGLWidget's context is not current"); + } + + cvf::String sLineInfo = cvf::String("OpenGL line width range: aliased lines: %1 to %2, smooth lines: %3 to %4").arg(aliasedLineWidthRange[0]).arg(aliasedLineWidthRange[1]).arg(smoothLineWidthRange[0]).arg(smoothLineWidthRange[1]); + cvf::String sPointInfo = cvf::String("OpenGL point size range: aliased points: %1 to %2, smooth points: %3 to %4").arg(aliasedPointSizeRange[0]).arg(aliasedPointSizeRange[1]).arg(smoothPointSizeRange[0]).arg(smoothPointSizeRange[1]); + CVF_LOG_INFO(m_logger, sLineInfo); + CVF_LOG_INFO(m_logger, sPointInfo); + + CVF_LOG_INFO(m_logger, "Finished logging of OpenGL info"); +} + + +} // namespace cvfqt + + diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget.h b/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget.h new file mode 100644 index 0000000000..dd2cc736a3 --- /dev/null +++ b/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget.h @@ -0,0 +1,86 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" + +#include + +namespace cvf { + class OpenGLContext; + class OpenGLContextGroup; + class Logger; +} + +namespace cvfqt { + + + +//================================================================================================== +// +// +// +//================================================================================================== +class GLWidget : public QGLWidget +{ +public: + GLWidget(cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent, Qt::WindowFlags f = Qt::WindowFlags()); + GLWidget(GLWidget* shareWidget, QWidget* parent , Qt::WindowFlags f = Qt::WindowFlags()); + ~GLWidget(); + + cvf::OpenGLContext* cvfOpenGLContext(); + void cvfShutdownOpenGLContext(); + + void logOpenGLInfo(); + +protected: + virtual void initializeGL(); + virtual void resizeGL(int width, int height); + virtual void paintGL(); + virtual bool eventFilter(QObject* watched, QEvent* event); + +private: + void qtOpenGLContextAboutToBeDestroyed(); + +private: + cvf::ref m_cvfOpenGLContextGroup; + cvf::ref m_cvfForwardingOpenGLContext; + cvf::ref m_logger; +}; + +} diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget_deprecated.cpp b/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget_deprecated.cpp new file mode 100644 index 0000000000..308f3b267a --- /dev/null +++ b/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget_deprecated.cpp @@ -0,0 +1,164 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#include "cvfBase.h" +#include "cvfOpenGLContextGroup.h" +#include "cvfqtCvfBoundQGLContext_deprecated.h" +#include "cvfqtGLWidget_deprecated.h" + +namespace cvfqt { + + + +//================================================================================================== +/// +/// \class cvfqt::GLWidget_deprecated +/// \ingroup GuiQt +/// +/// +/// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +GLWidget_deprecated::GLWidget_deprecated(cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent, Qt::WindowFlags f) +: QGLWidget(new CvfBoundQGLContext_deprecated(contextGroup, format), parent, NULL, f) +{ + // This constructor can only be used with an empty context group! + // We're not able to check this up front, but assert that the count is 1 by the time we get here + CVF_ASSERT(contextGroup->contextCount() == 1); + + if (isValid()) + { + cvf::ref myContext = cvfOpenGLContext(); + if (myContext.notNull()) + { + // We must ensure the context is current before initialization + makeCurrent(); + contextGroup->initializeContextGroup(myContext.p()); + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// Constructor +/// +/// Tries to create a widget that shares OpenGL resources with \a shareWidget +/// To check if creation was actually successful, you must call isValidContext() on the context +/// of the newly created widget. For example: +/// \code +/// myNewWidget->cvfOpenGLContext()->isValidContext(); +/// \endcode +/// +/// If the context is not valid, sharing failed and the newly created widget/context be discarded. +//-------------------------------------------------------------------------------------------------- +GLWidget_deprecated::GLWidget_deprecated(GLWidget_deprecated* shareWidget, QWidget* parent , Qt::WindowFlags f) +: QGLWidget(new CvfBoundQGLContext_deprecated(shareWidget->cvfOpenGLContext()->group(), shareWidget->format()), parent, shareWidget, f) +{ + CVF_ASSERT(shareWidget); + cvf::ref shareContext = shareWidget->cvfOpenGLContext(); + CVF_ASSERT(shareContext.notNull()); + + cvf::ref myContext = cvfOpenGLContext(); + if (myContext.notNull()) + { + cvf::OpenGLContextGroup* myOwnerContextGroup = myContext->group(); + CVF_ASSERT(myOwnerContextGroup == shareContext->group()); + + // We need to check if we actually got a context that shares resources with shareWidget. + if (isSharing()) + { + if (isValid()) + { + makeCurrent(); + myOwnerContextGroup->initializeContextGroup(myContext.p()); + } + } + else + { + // If we didn't, we need to remove the newly created context from the group it has been added to since + // the construction process above has already optimistically added the new context to the existing group. + // In this case, the newly context is basically defunct so we just shut it down (which will also remove it from the group) + // Normally, we would need to ensure the context is current before calling shutdown, but in this case we are not the last + // context in the group so there should be no need for cleaning up resources. + myOwnerContextGroup->contextAboutToBeShutdown(myContext.p()); + CVF_ASSERT(myContext->group() == NULL); + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::OpenGLContext* GLWidget_deprecated::cvfOpenGLContext() const +{ + const QGLContext* qglContext = context(); + const CvfBoundQGLContext_deprecated* contextBinding = dynamic_cast(qglContext); + CVF_ASSERT(contextBinding); + + return contextBinding->cvfOpenGLContext(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void GLWidget_deprecated::cvfShutdownOpenGLContext() +{ + // It should be safe to call shutdown multiple times so this call should + // amount to a no-op if the user has already shut down the context + cvf::ref myContext = cvfOpenGLContext(); + if (myContext.notNull()) + { + cvf::OpenGLContextGroup* myOwnerContextGroup = myContext->group(); + + // If shutdown has already been called, the context is no longer member of any group + if (myOwnerContextGroup) + { + makeCurrent(); + myOwnerContextGroup->contextAboutToBeShutdown(myContext.p()); + } + } +} + + +} // namespace cvfqt + + diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget_deprecated.h b/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget_deprecated.h new file mode 100644 index 0000000000..04a3962763 --- /dev/null +++ b/Fwk/VizFwk/LibGuiQt/cvfqtGLWidget_deprecated.h @@ -0,0 +1,66 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#pragma once + +#include + +namespace cvf +{ + class OpenGLContext; + class OpenGLContextGroup; +} + +namespace cvfqt { + + +//================================================================================================== +// +// Derived QGLWidget +// +//================================================================================================== +class GLWidget_deprecated : public QGLWidget +{ +public: + GLWidget_deprecated(cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent, Qt::WindowFlags f = Qt::WindowFlags()); + GLWidget_deprecated(GLWidget_deprecated* shareWidget, QWidget* parent , Qt::WindowFlags f = Qt::WindowFlags()); + + cvf::OpenGLContext* cvfOpenGLContext() const; + void cvfShutdownOpenGLContext(); +}; + +} diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLWidget.cpp b/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLWidget.cpp index fbfb54f65a..7de4e4c06e 100644 --- a/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLWidget.cpp +++ b/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLWidget.cpp @@ -34,117 +34,301 @@ // //################################################################################################## - -#include "cvfBase.h" -#include "cvfOpenGLContextGroup.h" -#include "cvfqtCvfBoundQGLContext.h" #include "cvfqtOpenGLWidget.h" +#include "cvfTrace.h" +#include "cvfString.h" +#include "cvfOpenGLContext.h" +#include "cvfLogManager.h" + +#include +#include +#include +#include + namespace cvfqt { //================================================================================================== -/// -/// \class cvfqt::OpenGLWidget -/// \ingroup GuiQt -/// -/// -/// +// +// +// //================================================================================================== +class ForwardingOpenGLContext_OpenGLWidget : public cvf::OpenGLContext +{ +public: + ForwardingOpenGLContext_OpenGLWidget(cvf::OpenGLContextGroup* contextGroup, QOpenGLWidget* ownerQtOpenGLWidget) + : cvf::OpenGLContext(contextGroup), + m_ownerQtOpenGLWidget(ownerQtOpenGLWidget) + { + CVF_ASSERT(contextGroup); + + // In our current usage pattern the owner widget (and its contained Qt OpenGL context) + // must already be initialized/created + CVF_ASSERT(m_ownerQtOpenGLWidget); + CVF_ASSERT(m_ownerQtOpenGLWidget->isValid()); + CVF_ASSERT(m_ownerQtOpenGLWidget->context()); + CVF_ASSERT(m_ownerQtOpenGLWidget->context()->isValid()); + } + + virtual void makeCurrent() + { + if (m_ownerQtOpenGLWidget) + { + m_ownerQtOpenGLWidget->makeCurrent(); + } + } + + virtual bool isCurrent() const + { + QOpenGLContext* ownersContext = m_ownerQtOpenGLWidget ? m_ownerQtOpenGLWidget->context() : NULL; + if (ownersContext && QOpenGLContext::currentContext() == ownersContext) + { + return true; + } + + return false; + } + + virtual cvf::OglId defaultFramebufferObject() const + { + if (m_ownerQtOpenGLWidget) + { + return m_ownerQtOpenGLWidget->defaultFramebufferObject(); + } + + return 0; + } + + QOpenGLWidget* ownerQtOpenGLWidget() + { + return m_ownerQtOpenGLWidget; + } + +private: + QPointer m_ownerQtOpenGLWidget; +}; + + + + +//================================================================================================== +// +// +// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +OpenGLWidget::OpenGLWidget(cvf::OpenGLContextGroup* contextGroup, QWidget* parent, Qt::WindowFlags f) +: QOpenGLWidget(parent, f), + m_instanceNumber(-1), + m_initializationState(UNINITIALIZED), + m_cvfOpenGlContextGroup(contextGroup), + m_logger(CVF_GET_LOGGER("cee.cvf.qt")) +{ + static int sl_nextInstanceNumber = 0; + m_instanceNumber = sl_nextInstanceNumber++; + + CVF_LOG_DEBUG(m_logger, cvf::String("OpenGLWidget[%1]::OpenGLWidget()").arg(m_instanceNumber)); + + CVF_ASSERT(m_cvfOpenGlContextGroup.notNull()); +} //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -OpenGLWidget::OpenGLWidget(cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent, Qt::WindowFlags f) -: QGLWidget(new CvfBoundQGLContext(contextGroup, format), parent, NULL, f) +OpenGLWidget::~OpenGLWidget() { - // This constructor can only be used with an empty context group! - // We're not able to check this up front, but assert that the count is 1 by the time we get here - CVF_ASSERT(contextGroup->contextCount() == 1); + CVF_LOG_DEBUG(m_logger, cvf::String("OpenGLWidget[%1]::~OpenGLWidget()").arg(m_instanceNumber)); - if (isValid()) + if (m_initializationState == IS_INITIALIZED) { - cvf::ref myContext = cvfOpenGLContext(); - if (myContext.notNull()) + // Make sure we disconnect from the aboutToBeDestroyed signal since after this destructor has been + // called, our object is dangling and the call to the slot will cause a crash + QOpenGLContext* myQtOpenGLContext = context(); + if (myQtOpenGLContext) { - myContext->initializeContext(); + disconnect(myQtOpenGLContext, &QOpenGLContext::aboutToBeDestroyed, this, &OpenGLWidget::qtOpenGLContextAboutToBeDestroyed); } } -} + shutdownCvfOpenGLContext(); +} //-------------------------------------------------------------------------------------------------- -/// Constructor -/// -/// Tries to create a widget that shares OpenGL resources with \a shareWidget -/// To check if creation was actually successful, you must call isValidContext() on the context -/// of the newly created widget. For example: -/// \code -/// myNewWidget->cvfOpenGLContext()->isValidContext(); -/// \endcode -/// -/// If the context is not valid, sharing failed and the newly created widget/context be discarded. +/// This is where we do the custom initialization needed for the Qt binding to work +/// +/// Note that if you re-implement this function in your subclass, you must make +/// sure to call the base class. //-------------------------------------------------------------------------------------------------- -OpenGLWidget::OpenGLWidget(OpenGLWidget* shareWidget, QWidget* parent , Qt::WindowFlags f) -: QGLWidget(new CvfBoundQGLContext(shareWidget->cvfOpenGLContext()->group(), shareWidget->format()), parent, shareWidget, f) +void OpenGLWidget::initializeGL() { - CVF_ASSERT(shareWidget); - cvf::ref shareContext = shareWidget->cvfOpenGLContext(); - CVF_ASSERT(shareContext.notNull()); + CVF_LOG_DEBUG(m_logger, cvf::String("OpenGLWidget[%1]::initializeGL()").arg(m_instanceNumber)); - cvf::ref myContext = cvfOpenGLContext(); - if (myContext.notNull()) + if (!isValid()) { - // We need to check if we actually got a context that shares resources with shareWidget. - if (isSharing()) + CVF_LOG_WARNING(m_logger, cvf::String("OpenGLWidget[%1]: Widget is not valid for initialization").arg(m_instanceNumber)); + } + + // According to Qt doc this function is called once before the first call to paintGL() or resizeGL(). + // Further it is stated that this widget's QOpenGLContext is already current. + // We should be able to assume that we will only be called with a create, valid and current QOpenGLContext + // + // Note that in some scenarios, such as when a widget get reparented, initializeGL() ends up being called + // multiple times in the lifetime of the widget. In those cases, the widget's associated context is first destroyed + // and then a new one is created. This is then followed by a new call to initializeGL() where all OpenGL resources must get reinitialized. + + QOpenGLContext* myQtOpenGLContext = context(); + CVF_ASSERT(myQtOpenGLContext); + CVF_ASSERT(myQtOpenGLContext->isValid()); + CVF_ASSERT(QOpenGLContext::currentContext() == myQtOpenGLContext); + + if (m_initializationState != IS_INITIALIZED) + { + CVF_LOG_DEBUG(m_logger, cvf::String("OpenGLWidget[%1]: Starting internal initialization").arg(m_instanceNumber)); + + // This should either be the first call or the result of a destroy/recreate cycle + CVF_ASSERT(m_cvfForwardingOpenGlContext.isNull()); + + // Try and detect the situation where the user is trying to associate incompatible widgets/contexts in the same cvf OpenGLContextGroup + // The assert below will fail if two incompatible OpenGL contexts end up in the same context group + if (m_cvfOpenGlContextGroup->contextCount() > 0) { - if (isValid()) + for (size_t i = 0; i < m_cvfOpenGlContextGroup->contextCount(); i++) { - CVF_ASSERT(myContext->group() == shareContext->group()); - myContext->initializeContext(); + ForwardingOpenGLContext_OpenGLWidget* existingFwdContext = dynamic_cast(m_cvfOpenGlContextGroup->context(i)); + QOpenGLWidget* existingWidget = existingFwdContext ? existingFwdContext->ownerQtOpenGLWidget() : NULL; + QOpenGLContext* existingQtContext = existingWidget ? existingWidget->context() : NULL; + if (existingQtContext) + { + // Assert that these two contexts are actually sharing OpenGL resources + CVF_ASSERT(QOpenGLContext::areSharing(existingQtContext, myQtOpenGLContext)); + } } } - else + + // Create the actual wrapper/forwarding OpenGL context that implements the cvf::OpenGLContext that we need + cvf::ref myCvfContext = new ForwardingOpenGLContext_OpenGLWidget(m_cvfOpenGlContextGroup.p(), this); + + // Possibly initialize the context group + if (!m_cvfOpenGlContextGroup->isContextGroupInitialized()) + { + if (!m_cvfOpenGlContextGroup->initializeContextGroup(myCvfContext.p())) + { + CVF_LOG_ERROR(m_logger, cvf::String("OpenGLWidget[%1]: OpenGL context creation failed, could not initialize context group").arg(m_instanceNumber)); + return; + } + } + + // All is well, so store pointer to the cvf OpenGL context + m_cvfForwardingOpenGlContext = myCvfContext; + + const InitializationState prevInitState = m_initializationState; + m_initializationState = IS_INITIALIZED; + + // Connect to signal so we get notified when Qt's OpenGL context is about to be destroyed + connect(myQtOpenGLContext, &QOpenGLContext::aboutToBeDestroyed, this, &OpenGLWidget::qtOpenGLContextAboutToBeDestroyed); + + if (prevInitState == UNINITIALIZED) + { + // Call overridable notification function to indicate that OpenGL has been initialized + // Don't do this if we're being re-initialized + onWidgetOpenGLReady(); + } + + // Trigger a repaint if we're being re-initialized + if (prevInitState == PENDING_REINITIALIZATION) { - // If we didn't, we need to remove the newly created context from the group it has been added to since - // the construction process above has already optimistically added the new context to the existing group. - // In this case, the newly context is basically defunct so we just shut it down (which will also remove it from the group) - myContext->shutdownContext(); - CVF_ASSERT(myContext->group() == NULL); + update(); } } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void OpenGLWidget::resizeGL(int /*w*/, int /*h*/) +{ + // Empty, should normally be implemented in derived class +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void OpenGLWidget::paintGL() +{ + // No implementation here (nor in QOpenGLWidget::paintGL()) + // Derived classes must re-implement this function in order to do painting. + // + // Typical code would go something like this: + // cvf::OpenGLContext* currentOglContext = cvfOpenGLContext(); + // myRenderSequence->render(currentOglContext); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::OpenGLContext* OpenGLWidget::cvfOpenGLContext() +{ + return m_cvfForwardingOpenGlContext.p(); +} //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::OpenGLContext* OpenGLWidget::cvfOpenGLContext() const +int OpenGLWidget::instanceNumber() const { - const QGLContext* qglContext = context(); - const CvfBoundQGLContext* contextBinding = dynamic_cast(qglContext); - CVF_ASSERT(contextBinding); + return m_instanceNumber; +} - return contextBinding->cvfOpenGLContext(); +//-------------------------------------------------------------------------------------------------- +/// Notification function that will be called after internal CVF OpenGL initialization has +/// successfully completed. This includes both the creation of the CVF OpenGLContext and +/// successful initialization of the OpenGL context group +/// +/// Can be re-implemented in derived classes to take any needed actions. +//-------------------------------------------------------------------------------------------------- +void OpenGLWidget::onWidgetOpenGLReady() +{ + // Base implementation does nothing } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void OpenGLWidget::qtOpenGLContextAboutToBeDestroyed() +{ + CVF_LOG_DEBUG(m_logger, cvf::String("OpenGLWidget[%1]::qtOpenGLContextAboutToBeDestroyed()").arg(m_instanceNumber)); + + if (m_cvfForwardingOpenGlContext.notNull()) + { + CVF_LOG_DEBUG(m_logger, cvf::String("OpenGLWidget[%1]: Shutting down CVF OpenGL context since Qt context is about to be destroyed").arg(m_instanceNumber)); + shutdownCvfOpenGLContext(); + } + + if (m_initializationState == IS_INITIALIZED) + { + m_initializationState = PENDING_REINITIALIZATION; + } +} //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void OpenGLWidget::cvfShutdownOpenGLContext() +void OpenGLWidget::shutdownCvfOpenGLContext() { - // It should be safe to call shutdown multiple times so this call should - // amount to a no-op if the user has already shut down the context - cvf::ref myContext = cvfOpenGLContext(); - if (myContext.notNull()) + if (m_cvfForwardingOpenGlContext.notNull()) { - myContext->shutdownContext(); + makeCurrent(); + + m_cvfOpenGlContextGroup->contextAboutToBeShutdown(m_cvfForwardingOpenGlContext.p()); + m_cvfForwardingOpenGlContext = NULL; } } } // namespace cvfqt - diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLWidget.h b/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLWidget.h index c598f9997d..9b797cd27d 100644 --- a/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLWidget.h +++ b/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLWidget.h @@ -34,33 +34,63 @@ // //################################################################################################## - #pragma once -#include +#include "cvfBase.h" +#include "cvfObject.h" -namespace cvf -{ +#include + +namespace cvf { class OpenGLContext; class OpenGLContextGroup; + class Logger; } namespace cvfqt { + //================================================================================================== // -// Derived QGLWidget +// // //================================================================================================== -class OpenGLWidget : public QGLWidget +class OpenGLWidget : public QOpenGLWidget { public: - OpenGLWidget(cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent, Qt::WindowFlags f = 0); - OpenGLWidget(OpenGLWidget* shareWidget, QWidget* parent , Qt::WindowFlags f = 0); + OpenGLWidget(cvf::OpenGLContextGroup* contextGroup, QWidget* parent, Qt::WindowFlags f = Qt::WindowFlags()); + ~OpenGLWidget(); + + cvf::OpenGLContext* cvfOpenGLContext(); + +protected: + virtual void initializeGL(); + virtual void resizeGL(int w, int h); + virtual void paintGL(); + + int instanceNumber() const; - cvf::OpenGLContext* cvfOpenGLContext() const; - void cvfShutdownOpenGLContext(); + virtual void onWidgetOpenGLReady(); + +private: + void qtOpenGLContextAboutToBeDestroyed(); + void shutdownCvfOpenGLContext(); + +private: + enum InitializationState + { + UNINITIALIZED, + PENDING_REINITIALIZATION, + IS_INITIALIZED + }; + + int m_instanceNumber; + InitializationState m_initializationState; + cvf::ref m_cvfOpenGlContextGroup; + cvf::ref m_cvfForwardingOpenGlContext; + cvf::ref m_logger; }; -} + +} \ No newline at end of file diff --git a/Fwk/VizFwk/LibIo/cvfXml.cpp b/Fwk/VizFwk/LibIo/cvfXml.cpp index 47e445838b..c4c53bb81e 100644 --- a/Fwk/VizFwk/LibIo/cvfXml.cpp +++ b/Fwk/VizFwk/LibIo/cvfXml.cpp @@ -45,8 +45,15 @@ #pragma warning( disable : 4365 ) #endif +CVF_GCC_DIAGNOSTIC_PUSH +#if defined (CVF_GCC_VER) && (CVF_GCC_VER >= 70400) +CVF_GCC_DIAGNOSTIC_IGNORE("-Wimplicit-fallthrough=") +#endif + #include "cvfTinyXmlFused.hpp" +CVF_GCC_DIAGNOSTIC_POP + #ifdef _MSC_VER #pragma warning( pop ) #endif diff --git a/Fwk/VizFwk/LibRender/CMakeLists.txt b/Fwk/VizFwk/LibRender/CMakeLists.txt index 3b0e23d5b0..94759337b4 100644 --- a/Fwk/VizFwk/LibRender/CMakeLists.txt +++ b/Fwk/VizFwk/LibRender/CMakeLists.txt @@ -45,8 +45,10 @@ cvfOpenGL.h cvfOpenGLCapabilities.h cvfOpenGLContext.h cvfOpenGLContextGroup.h +cvfOpenGLInfo.h cvfOpenGLResourceManager.h cvfOpenGLTypes.h +cvfOpenGLUtils.h cvfOverlayAxisCross.h cvfOverlayScalarMapperLegend.h cvfOverlayColorLegend.h @@ -122,7 +124,9 @@ cvfOglRc.cpp cvfOpenGLCapabilities.cpp cvfOpenGLContext.cpp cvfOpenGLContextGroup.cpp +cvfOpenGLInfo.cpp cvfOpenGLResourceManager.cpp +cvfOpenGLUtils.cpp cvfOpenGL.cpp cvfOverlayAxisCross.cpp cvfOverlayScalarMapperLegend.cpp diff --git a/Fwk/VizFwk/LibRender/cvfFramebufferObject.cpp b/Fwk/VizFwk/LibRender/cvfFramebufferObject.cpp index 721da2f883..dc6cd59917 100644 --- a/Fwk/VizFwk/LibRender/cvfFramebufferObject.cpp +++ b/Fwk/VizFwk/LibRender/cvfFramebufferObject.cpp @@ -485,8 +485,13 @@ void FramebufferObject::useDefaultWindowFramebuffer(OpenGLContext* oglContext) { CVF_CALLSITE_OPENGL(oglContext); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glDrawBuffer(GL_BACK); + const OglId defaultFBO = oglContext->defaultFramebufferObject(); + glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO); + + if (defaultFBO == 0) + { + glDrawBuffer(GL_BACK); + } CVF_CHECK_OGL(oglContext); } diff --git a/Fwk/VizFwk/LibRender/cvfLibRender.h b/Fwk/VizFwk/LibRender/cvfLibRender.h index c24391290b..1821a4fcd6 100644 --- a/Fwk/VizFwk/LibRender/cvfLibRender.h +++ b/Fwk/VizFwk/LibRender/cvfLibRender.h @@ -61,6 +61,7 @@ #include "cvfOpenGLContextGroup.h" #include "cvfOpenGLResourceManager.h" #include "cvfOpenGLTypes.h" +#include "cvfOpenGLUtils.h" #include "cvfOverlayAxisCross.h" #include "cvfOverlayColorLegend.h" #include "cvfOverlayImage.h" diff --git a/Fwk/VizFwk/LibRender/cvfOpenGLContext.cpp b/Fwk/VizFwk/LibRender/cvfOpenGLContext.cpp index f993313996..db9151f7e8 100644 --- a/Fwk/VizFwk/LibRender/cvfOpenGLContext.cpp +++ b/Fwk/VizFwk/LibRender/cvfOpenGLContext.cpp @@ -59,8 +59,7 @@ namespace cvf { /// The context will be added unconditionally to the \a contextGroup group //-------------------------------------------------------------------------------------------------- OpenGLContext::OpenGLContext(OpenGLContextGroup* contextGroup) -: m_contextGroup(contextGroup), - m_isValid(false) +: m_contextGroup(contextGroup) { CVF_ASSERT(m_contextGroup); m_contextGroup->addContext(this); @@ -74,8 +73,6 @@ OpenGLContext::~OpenGLContext() { //Trace::show("OpenGLContext destructor"); - m_isValid = false; - // Context group is holding references to contexts, so by the time we get to this // destructor the link to the context group must already be broken CVF_ASSERT(m_contextGroup == NULL); @@ -87,8 +84,7 @@ OpenGLContext::~OpenGLContext() //-------------------------------------------------------------------------------------------------- bool OpenGLContext::isContextValid() const { - // Also check on context group, since it may have been set to NULL after valid flag was set - if (m_contextGroup && m_isValid) + if (m_contextGroup && m_contextGroup->isContextGroupInitialized()) { return true; } @@ -102,59 +98,9 @@ bool OpenGLContext::isContextValid() const //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -bool OpenGLContext::initializeContext() +OglId OpenGLContext::defaultFramebufferObject() const { - makeCurrent(); - - if (!m_contextGroup) - { - return false; - } - - if (!m_contextGroup->isContextGroupInitialized()) - { - if (!m_contextGroup->initializeContextGroup(this)) - { - return false; - } - } - - m_isValid = true; - - return true; -} - - -//-------------------------------------------------------------------------------------------------- -/// Prepare the context for deletion -/// -/// Prepares the context for deletion by removing the context from its context group. If this is the -/// last context in the context group, this function will also try and delete the context group's -/// OpenGL resources. -/// -/// \warning After calling this function the context is no longer usable and should be deleted. -/// \warning May try and make the context current in order to free resources if this context -/// is the last context in the context group. -//-------------------------------------------------------------------------------------------------- -void OpenGLContext::shutdownContext() -{ - if (m_contextGroup) - { - CVF_ASSERT(m_contextGroup->containsContext(this)); - - // If our ref count is down to 1, there is probably something strange going on. - // Since one reference to us is being held by the context group, this means that the - // caller ISN'T holding a reference which may give him a nast surprise when this function returns! - CVF_ASSERT(refCount() > 1); - - // This call will remove the context from the group AND clean up resources in the - // group if we are the last context in the group - m_contextGroup->contextAboutToBeShutdown(this); - } - - CVF_ASSERT(m_contextGroup == NULL); - - m_isValid = false; + return 0; } diff --git a/Fwk/VizFwk/LibRender/cvfOpenGLContext.h b/Fwk/VizFwk/LibRender/cvfOpenGLContext.h index 254a656c60..2dc7af7b17 100644 --- a/Fwk/VizFwk/LibRender/cvfOpenGLContext.h +++ b/Fwk/VizFwk/LibRender/cvfOpenGLContext.h @@ -39,6 +39,7 @@ #include "cvfObject.h" #include "cvfOpenGLContextGroup.h" +#include "cvfOpenGLTypes.h" namespace cvf { @@ -58,11 +59,10 @@ class OpenGLContext : public Object virtual ~OpenGLContext(); bool isContextValid() const; - virtual bool initializeContext(); - virtual void shutdownContext(); virtual void makeCurrent() = 0; virtual bool isCurrent() const = 0; + virtual OglId defaultFramebufferObject() const; OpenGLContextGroup* group(); const OpenGLContextGroup* group() const; @@ -71,7 +71,6 @@ class OpenGLContext : public Object private: OpenGLContextGroup* m_contextGroup; // Raw pointer (to avoid circular reference) to the context group that this context belongs to. - bool m_isValid; // Will be set to true after successful initialization friend class OpenGLContextGroup; }; diff --git a/Fwk/VizFwk/LibRender/cvfOpenGLContextGroup.cpp b/Fwk/VizFwk/LibRender/cvfOpenGLContextGroup.cpp index 006f0fba96..a1779e2594 100644 --- a/Fwk/VizFwk/LibRender/cvfOpenGLContextGroup.cpp +++ b/Fwk/VizFwk/LibRender/cvfOpenGLContextGroup.cpp @@ -42,6 +42,7 @@ #include "cvfOpenGLResourceManager.h" #include "cvfOpenGLCapabilities.h" #include "cvfLogManager.h" +#include "cvfTrace.h" #include @@ -75,6 +76,8 @@ OpenGLContextGroup::OpenGLContextGroup() m_glewContextStruct(NULL), m_wglewContextStruct(NULL) { + //Trace::show("OpenGLContextGroup constructor"); + m_resourceManager = new OpenGLResourceManager; m_logger = CVF_GET_LOGGER("cee.cvf.OpenGL"); m_capabilities = new OpenGLCapabilities; @@ -105,7 +108,10 @@ OpenGLContextGroup::~OpenGLContextGroup() m_contexts.clear(); - uninitializeContextGroup(); + if (m_isInitialized) + { + uninitializeContextGroup(); + } } @@ -129,6 +135,8 @@ bool OpenGLContextGroup::isContextGroupInitialized() const //-------------------------------------------------------------------------------------------------- bool OpenGLContextGroup::initializeContextGroup(OpenGLContext* currentContext) { + //Trace::show("OpenGLContextGroup::initializeContextGroup()"); + CVF_ASSERT(currentContext); CVF_ASSERT(currentContext->isCurrent()); CVF_ASSERT(containsContext(currentContext)); @@ -139,20 +147,27 @@ bool OpenGLContextGroup::initializeContextGroup(OpenGLContext* currentContext) if (!initializeGLEW(currentContext)) { + CVF_LOG_ERROR(m_logger.p(), "Failed to intitialize GLEW in context group"); return false; } - configureCapablititesFromGLEW(currentContext); + configureCapabilitiesFromGLEW(currentContext); #ifdef WIN32 if (!initializeWGLEW(currentContext)) { + CVF_LOG_ERROR(m_logger.p(), "Failed to intitialize WGLEW in context group"); return false; } #endif #endif + CVF_LOG_DEBUG(m_logger.p(), "OpenGL initialized in context group"); + CVF_LOG_DEBUG(m_logger.p(), " version: " + m_info.version()); + CVF_LOG_DEBUG(m_logger.p(), " vendor: " + m_info.vendor()); + CVF_LOG_DEBUG(m_logger.p(), " renderer: " + m_info.renderer()); + m_isInitialized = true; } @@ -165,10 +180,12 @@ bool OpenGLContextGroup::initializeContextGroup(OpenGLContext* currentContext) //-------------------------------------------------------------------------------------------------- void OpenGLContextGroup::uninitializeContextGroup() { + //Trace::show("OpenGLContextGroup::uninitializeContextGroup()"); + CVF_ASSERT(m_contexts.empty()); CVF_ASSERT(!m_resourceManager->hasAnyOpenGLResources()); - // Just replace capablities with a new object + // Just replace capabilities with a new object m_capabilities = new OpenGLCapabilities; #ifdef CVF_USE_GLEW @@ -186,28 +203,30 @@ void OpenGLContextGroup::uninitializeContextGroup() //-------------------------------------------------------------------------------------------------- -/// Called by OpenGLContext objects when they are being shut down +/// Prepare a context for deletion /// -/// This function will remove the context \a contextToShutdown from the context group. -/// If \a contextToShutdown is the last context in the group, all resources in the group's +/// This function will remove the context \a currentContextToShutdown from the context group. +/// If \a currentContextToShutdown is the last context in the group, all resources in the group's /// resource manager will be deleted and the context group will be reset to uninitialized. /// -/// \warning This function may try and make the context passed in \a contextToShutdown curreent! +/// \warning The passed context must be the current OpenGL context! +/// \warning After calling this function the context is no longer usable and should be deleted. //-------------------------------------------------------------------------------------------------- -void OpenGLContextGroup::contextAboutToBeShutdown(OpenGLContext* contextToShutdown) +void OpenGLContextGroup::contextAboutToBeShutdown(OpenGLContext* currentContextToShutdown) { - CVF_ASSERT(contextToShutdown); - CVF_ASSERT(containsContext(contextToShutdown)); + //Trace::show("OpenGLContextGroup::contextAboutToBeShutdown()"); + + CVF_ASSERT(currentContextToShutdown); + CVF_ASSERT(containsContext(currentContextToShutdown)); // If this is the last context in the group, we'll delete all the OpenGL resources in the s resource manager before we go bool shouldUninitializeGroup = false; if (contextCount() == 1) { CVF_ASSERT(m_resourceManager.notNull()); - if (m_resourceManager->hasAnyOpenGLResources() && contextToShutdown->isContextValid()) + if (m_resourceManager->hasAnyOpenGLResources() && currentContextToShutdown->isContextValid()) { - contextToShutdown->makeCurrent(); - m_resourceManager->deleteAllOpenGLResources(contextToShutdown); + m_resourceManager->deleteAllOpenGLResources(currentContextToShutdown); } shouldUninitializeGroup = true; @@ -217,12 +236,12 @@ void OpenGLContextGroup::contextAboutToBeShutdown(OpenGLContext* contextToShutdo // Since one reference to the context is being held by this context group, this means that the // caller isn't holding a reference to the context. In this case the context object will evaporate // during the call below, and the caller will most likely get a nasty surprise - CVF_ASSERT(contextToShutdown->refCount() > 1); + CVF_ASSERT(currentContextToShutdown->refCount() > 1); // Make sure we set the back pointer before removing it from our collection // since the removal from the list may actually trigger destruction of the context (see comment above) - contextToShutdown->m_contextGroup = NULL; - m_contexts.erase(contextToShutdown); + currentContextToShutdown->m_contextGroup = NULL; + m_contexts.erase(currentContextToShutdown); if (shouldUninitializeGroup) { @@ -239,11 +258,23 @@ void OpenGLContextGroup::contextAboutToBeShutdown(OpenGLContext* contextToShutdo //-------------------------------------------------------------------------------------------------- bool OpenGLContextGroup::initializeGLEW(OpenGLContext* currentContext) { + //Trace::show("OpenGLContextGroup::initializeGLEW()"); + CVF_ASSERT(currentContext); CVF_ASSERT(m_glewContextStruct == NULL); #ifdef CVF_USE_GLEW + // Usage of GLEW requires that we have a standard OpenGL implementation available (not any Qt wrapper etc) + // Supposedly the version string should always contain at least one '.' + // Try and test this by querying the OpenGL version number and assume that there is no OpenGL available if it fails + const String sVersion(reinterpret_cast(glGetString(GL_VERSION))); + if (sVersion.find(".") == String::npos) + { + CVF_LOG_ERROR(m_logger, "Error initializing OpenGL functions, probe for OpenGL version failed. No valid OpenGL context is current"); + return false; + } + // Since we're sometimes (when using Core OpenGL) seeing some OGL errors from GLEW, check before and after call to help find them CVF_CHECK_OGL(currentContext); @@ -253,6 +284,7 @@ bool OpenGLContextGroup::initializeGLEW(OpenGLContext* currentContext) GLenum err = glewContextInit(theContextStruct); if (err != GLEW_OK) { + CVF_LOG_ERROR(m_logger, String("Error initializing GLEW, glewContextInit() returned %1").arg(err)); delete theContextStruct; return false; } @@ -261,6 +293,10 @@ bool OpenGLContextGroup::initializeGLEW(OpenGLContext* currentContext) CVF_CHECK_OGL(currentContext); + String sVendor(reinterpret_cast(glGetString(GL_VENDOR))); + String sRenderer(reinterpret_cast(glGetString(GL_RENDERER))); + m_info.setOpenGLStrings(sVersion, sVendor, sRenderer); + #else CVF_FAIL_MSG("Not implemented"); @@ -315,7 +351,7 @@ bool OpenGLContextGroup::initializeWGLEW(OpenGLContext* currentContext) /// /// \warning The passed context must be current and GLEW must already be initialized! //-------------------------------------------------------------------------------------------------- -void OpenGLContextGroup::configureCapablititesFromGLEW(OpenGLContext* currentContext) +void OpenGLContextGroup::configureCapabilitiesFromGLEW(OpenGLContext* currentContext) { #ifdef CVF_USE_GLEW CVF_CALLSITE_GLEW(currentContext); @@ -362,6 +398,15 @@ size_t OpenGLContextGroup::contextCount() const } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::OpenGLContext* OpenGLContextGroup::context(size_t index) +{ + return m_contexts.at(index); +} + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -432,6 +477,15 @@ OpenGLCapabilities* OpenGLContextGroup::capabilities() } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +OpenGLInfo OpenGLContextGroup::info() const +{ + return m_info; +} + + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/VizFwk/LibRender/cvfOpenGLContextGroup.h b/Fwk/VizFwk/LibRender/cvfOpenGLContextGroup.h index 82268b4ca2..d8052bfb30 100644 --- a/Fwk/VizFwk/LibRender/cvfOpenGLContextGroup.h +++ b/Fwk/VizFwk/LibRender/cvfOpenGLContextGroup.h @@ -40,6 +40,8 @@ #include "cvfObject.h" #include "cvfCollection.h" #include "cvfLogger.h" +#include "cvfOpenGLCapabilities.h" +#include "cvfOpenGLInfo.h" struct GLEWContextStruct; struct WGLEWContextStruct; @@ -48,7 +50,6 @@ namespace cvf { class OpenGLContext; class OpenGLResourceManager; -class OpenGLCapabilities; //================================================================================================== @@ -63,24 +64,27 @@ class OpenGLContextGroup : public Object virtual ~OpenGLContextGroup(); bool isContextGroupInitialized() const; + bool initializeContextGroup(OpenGLContext* currentContext); + void contextAboutToBeShutdown(OpenGLContext* currentContextToShutdown); size_t contextCount() const; + OpenGLContext* context(size_t index); bool containsContext(const OpenGLContext* context) const; OpenGLResourceManager* resourceManager(); Logger* logger(); OpenGLCapabilities* capabilities(); + OpenGLInfo info() const; + GLEWContextStruct* glewContextStruct(); WGLEWContextStruct* wglewContextStruct(); private: - bool initializeContextGroup(OpenGLContext* currentContext); void uninitializeContextGroup(); - void contextAboutToBeShutdown(OpenGLContext* contextToShutdown); bool initializeGLEW(OpenGLContext* currentContext); bool initializeWGLEW(OpenGLContext* currentContext); - void configureCapablititesFromGLEW(OpenGLContext* currentContext); + void configureCapabilitiesFromGLEW(OpenGLContext* currentContext); void addContext(OpenGLContext* contextToAdd); private: @@ -89,6 +93,7 @@ class OpenGLContextGroup : public Object ref m_resourceManager; // Resource manager that is shared between all contexts in this group ref m_logger; ref m_capabilities; // Capabilities of the contexts in this group context + OpenGLInfo m_info; GLEWContextStruct* m_glewContextStruct; // Pointer to the GLEW context struct WGLEWContextStruct* m_wglewContextStruct; // Pointer to the GLEW context struct diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext.cpp b/Fwk/VizFwk/LibRender/cvfOpenGLInfo.cpp similarity index 69% rename from Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext.cpp rename to Fwk/VizFwk/LibRender/cvfOpenGLInfo.cpp index c3734d7af2..198c19b6af 100644 --- a/Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext.cpp +++ b/Fwk/VizFwk/LibRender/cvfOpenGLInfo.cpp @@ -36,58 +36,66 @@ #include "cvfBase.h" -#include "cvfqtCvfBoundQGLContext.h" -#include "cvfqtOpenGLContext.h" - -namespace cvfqt { +#include "cvfOpenGLInfo.h" +namespace cvf { //================================================================================================== /// -/// \class cvfqt::CvfBoundQGLContext -/// \ingroup GuiQt +/// \class cvf::OpenGLInfo +/// \ingroup Render /// /// -/// +/// //================================================================================================== //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -CvfBoundQGLContext::CvfBoundQGLContext(cvf::OpenGLContextGroup* contextGroup, const QGLFormat & format) -: QGLContext(format) +OpenGLInfo::OpenGLInfo() { - m_cvfGLContext = new OpenGLContext(contextGroup, this); } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -CvfBoundQGLContext::~CvfBoundQGLContext() +OpenGLInfo::~OpenGLInfo() { - if (m_cvfGLContext.notNull()) - { - // TODO - // Need to resolve the case where the Qt QGLcontext (that we're deriving from) is deleted - // and we are still holding a reference to one or more OpenGLContext objects - // By the time we get here we expect that we're holding the only reference - CVF_ASSERT(m_cvfGLContext->refCount() == 1); - m_cvfGLContext = NULL; - } } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -cvf::OpenGLContext* CvfBoundQGLContext::cvfOpenGLContext() const +String OpenGLInfo::version() const { - return const_cast(m_cvfGLContext.p()); + return m_version; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +String OpenGLInfo::vendor() const +{ + return m_vendor; +} -} // namespace cvfqt +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +String OpenGLInfo::renderer() const +{ + return m_renderer; +} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void OpenGLInfo::setOpenGLStrings(String version, String vendor, String renderer) +{ + m_version = version; + m_vendor = vendor; + m_renderer = renderer; +} +} // namespace cvf diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext.h b/Fwk/VizFwk/LibRender/cvfOpenGLInfo.h similarity index 82% rename from Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext.h rename to Fwk/VizFwk/LibRender/cvfOpenGLInfo.h index 5160f372fc..fba0f01dd2 100644 --- a/Fwk/VizFwk/LibGuiQt/cvfqtCvfBoundQGLContext.h +++ b/Fwk/VizFwk/LibRender/cvfOpenGLInfo.h @@ -37,28 +37,32 @@ #pragma once -#include "cvfOpenGLContext.h" +#include "cvfString.h" -#include - -namespace cvfqt { +namespace cvf { //================================================================================================== // -// Utility class used to piggyback OpenGLContext onto Qt's QGLContext +// // //================================================================================================== -class CvfBoundQGLContext : public QGLContext +class OpenGLInfo { public: - CvfBoundQGLContext(cvf::OpenGLContextGroup* contextGroup, const QGLFormat & format); - virtual ~CvfBoundQGLContext(); + OpenGLInfo(); + ~OpenGLInfo(); + + String version() const; + String vendor() const; + String renderer() const; - cvf::OpenGLContext* cvfOpenGLContext() const; + void setOpenGLStrings(String version, String vendor, String renderer); private: - cvf::ref m_cvfGLContext; + String m_version; + String m_vendor; + String m_renderer; }; } diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLContext.cpp b/Fwk/VizFwk/LibRender/cvfOpenGLUtils.cpp similarity index 60% rename from Fwk/VizFwk/LibGuiQt/cvfqtOpenGLContext.cpp rename to Fwk/VizFwk/LibRender/cvfOpenGLUtils.cpp index 7d29682d30..70bb4440a8 100644 --- a/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLContext.cpp +++ b/Fwk/VizFwk/LibRender/cvfOpenGLUtils.cpp @@ -36,105 +36,30 @@ #include "cvfBase.h" +#include "cvfOpenGLUtils.h" #include "cvfOpenGL.h" -#include "cvfqtOpenGLContext.h" -#include "cvfqtCvfBoundQGLContext.h" - -#include "cvfOpenGLContextGroup.h" +#include "cvfOpenGLContext.h" #include "cvfOpenGLCapabilities.h" -namespace cvfqt { +namespace cvf { //================================================================================================== /// -/// \class cvfqt::OpenGLContext -/// \ingroup GuiQt +/// \class cvf::OpenGLUtils +/// \ingroup Render /// -/// Derived OpenGLContext that adapts a Qt QGLContext +/// Static class providing OpenGL helpers /// //================================================================================================== //-------------------------------------------------------------------------------------------------- +/// Store the current OpenGL context settings by using OpenGL's built in push methods. /// +/// Note: This call MUST be matched with a corresponding popOpenGLState() call. //-------------------------------------------------------------------------------------------------- -OpenGLContext::OpenGLContext(cvf::OpenGLContextGroup* contextGroup, QGLContext* backingQGLContext) -: cvf::OpenGLContext(contextGroup), - m_isCoreOpenGLProfile(false), - m_majorVersion(0), - m_minorVersion(0) -{ - m_qtGLContext = backingQGLContext; - - CVF_ASSERT(m_qtGLContext); - QGLFormat glFormat = m_qtGLContext->format(); - m_majorVersion = glFormat.majorVersion(); - m_minorVersion = glFormat.minorVersion(); - m_isCoreOpenGLProfile = (glFormat.profile() == QGLFormat::CoreProfile) ? true : false; -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -OpenGLContext::~OpenGLContext() -{ - m_qtGLContext = NULL; -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool OpenGLContext::initializeContext() -{ - if (!cvf::OpenGLContext::initializeContext()) - { - return false; - } - - // Possibly override setting for fixed function support - if (m_isCoreOpenGLProfile) - { - group()->capabilities()->setSupportsFixedFunction(false); - } - - return true; -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void OpenGLContext::makeCurrent() -{ - CVF_ASSERT(m_qtGLContext); - m_qtGLContext->makeCurrent(); -} - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -bool OpenGLContext::isCurrent() const -{ - if (m_qtGLContext) - { - if (QGLContext::currentContext() == m_qtGLContext) - { - return true; - } - } - - return false; -} - - -//-------------------------------------------------------------------------------------------------- -/// Make an effort to save current OpenGL state. Must be matched by a call to restoreOpenGLState() -//-------------------------------------------------------------------------------------------------- -void OpenGLContext::saveOpenGLState(cvf::OpenGLContext* oglContext) +void OpenGLUtils::pushOpenGLState(OpenGLContext* oglContext) { CVF_CALLSITE_OPENGL(oglContext); const cvf::OpenGLCapabilities* oglCaps = oglContext->capabilities(); @@ -178,9 +103,11 @@ void OpenGLContext::saveOpenGLState(cvf::OpenGLContext* oglContext) //-------------------------------------------------------------------------------------------------- -/// Restore OpenGL state that has been saved by saveOpenGLState() +/// Set back the stored OpenGL context settings by using OpenGL's built in pop methods. +/// +/// Note: This call MUST be matched with a corresponding pushOpenGLState() call. //-------------------------------------------------------------------------------------------------- -void OpenGLContext::restoreOpenGLState(cvf::OpenGLContext* oglContext) +void OpenGLUtils::popOpenGLState(OpenGLContext* oglContext) { CVF_CALLSITE_OPENGL(oglContext); const cvf::OpenGLCapabilities* oglCaps = oglContext->capabilities(); @@ -212,7 +139,7 @@ void OpenGLContext::restoreOpenGLState(cvf::OpenGLContext* oglContext) glPopAttrib(); CVF_CHECK_OGL(oglContext); - + // Currently not pushing vertex attribs, so comment out the pop //glPopClientAttrib(); @@ -221,6 +148,5 @@ void OpenGLContext::restoreOpenGLState(cvf::OpenGLContext* oglContext) } -} // namespace cvfqt - +} // namespace cvf diff --git a/Fwk/VizFwk/LibRender/cvfOpenGLUtils.h b/Fwk/VizFwk/LibRender/cvfOpenGLUtils.h new file mode 100644 index 0000000000..3297b18edd --- /dev/null +++ b/Fwk/VizFwk/LibRender/cvfOpenGLUtils.h @@ -0,0 +1,58 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#pragma once + +namespace cvf { + +class OpenGLContext; + + +//================================================================================================== +// +// +// +//================================================================================================== +class OpenGLUtils +{ +public: + static void pushOpenGLState(OpenGLContext* oglContext); + static void popOpenGLState(OpenGLContext* oglContext); +}; + +} + diff --git a/Fwk/VizFwk/LibRender/cvfRenderingScissor.cpp b/Fwk/VizFwk/LibRender/cvfRenderingScissor.cpp index 8effcd1ede..2e6cf0fae8 100644 --- a/Fwk/VizFwk/LibRender/cvfRenderingScissor.cpp +++ b/Fwk/VizFwk/LibRender/cvfRenderingScissor.cpp @@ -172,6 +172,8 @@ void RenderingScissor::unApplyOpenGL(OpenGLContext* oglContext) m_scissorBoxToRestore[1], m_scissorBoxToRestore[2], m_scissorBoxToRestore[3]); + + CVF_CHECK_OGL(oglContext); } } \ No newline at end of file diff --git a/Fwk/VizFwk/LibRender/cvfShader.cpp b/Fwk/VizFwk/LibRender/cvfShader.cpp index cc037a47fd..f578ff6f9e 100644 --- a/Fwk/VizFwk/LibRender/cvfShader.cpp +++ b/Fwk/VizFwk/LibRender/cvfShader.cpp @@ -181,6 +181,16 @@ bool Shader::compile(OpenGLContext* oglContext) String errStr = String("Error compiling shader: '%1'\n").arg(m_shaderName); errStr += "GLSL details:\n"; errStr += shaderInfoLog(oglContext); + + // { + // errStr += "Shader prog:\n"; + // std::vector progArr = m_source.split("\n"); + // for (size_t i = 0; i < progArr.size(); ++i) + // { + // errStr += String("%1: %2\n").arg(static_cast(i + 1), 3).arg(progArr[i]); + // } + // } + CVF_LOG_RENDER_ERROR(oglContext, errStr); return false; } diff --git a/Fwk/VizFwk/LibUtilities/CMakeLists.txt b/Fwk/VizFwk/LibUtilities/CMakeLists.txt index 6af391c21e..3409cf93d6 100644 --- a/Fwk/VizFwk/LibUtilities/CMakeLists.txt +++ b/Fwk/VizFwk/LibUtilities/CMakeLists.txt @@ -1,8 +1,14 @@ project(LibUtilities) -# Use our strict compile flags -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STRICT_CXX_FLAGS}") +# Use our strict compile flags only on windows since C++17 gives too +# much trouble in the JPEG code when using GCC +if (WIN32) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STRICT_CXX_FLAGS}") +else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_BASE_CXX_FLAGS}") +endif() + if (CMAKE_COMPILER_IS_GNUCXX) # Don't allow the compiler to assume strict aliasing when doing optimizations (the culprit is JPEG code) diff --git a/Fwk/VizFwk/LibUtilities/cvfuImageJpeg.cpp b/Fwk/VizFwk/LibUtilities/cvfuImageJpeg.cpp index c7ca8a5c01..90298096de 100644 --- a/Fwk/VizFwk/LibUtilities/cvfuImageJpeg.cpp +++ b/Fwk/VizFwk/LibUtilities/cvfuImageJpeg.cpp @@ -46,6 +46,9 @@ CVF_GCC_DIAGNOSTIC_IGNORE("-Wconversion") CVF_GCC_DIAGNOSTIC_IGNORE("-Wunused-parameter") +CVF_GCC_DIAGNOSTIC_IGNORE("-Wshift-negative-value") +CVF_GCC_DIAGNOSTIC_IGNORE("-Wimplicit-fallthrough=") +CVF_GCC_DIAGNOSTIC_IGNORE("-Wmisleading-indentation") #ifdef WIN32 #include @@ -56,6 +59,12 @@ CVF_GCC_DIAGNOSTIC_IGNORE("-Wunused-parameter") #include #endif + +// !!! +// Big time hack since C++17 does not allow ‘register’ storage class specifier +#define register + + // Doxygen conditional section to hide contents of the cvfu_jpgFreeImage namespace /// \cond CVF_NEVER_INCLUDE @@ -25126,7 +25135,7 @@ SetMemoryIO(FreeImageIO *io) { // // Design and implementation by // - Ryan Rubley -// - Herv Drolon (drolon@infonie.fr) +// - Herv� Drolon (drolon@infonie.fr) // // This file is part of FreeImage 3 // diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt index 59db47508d..437badd3f1 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal/CMakeLists.txt @@ -1,7 +1,7 @@ project(QtMinimal) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_BASE_CXX_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STANDARD_CXX_FLAGS}") if (CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long") @@ -10,6 +10,17 @@ endif() find_package(OpenGL) +if (CEE_USE_QT6) + find_package(Qt6 COMPONENTS REQUIRED OpenGLWidgets) + set(QT_LIBRARIES Qt6::OpenGLWidgets ) +elseif (CEE_USE_QT5) + find_package(Qt5 REQUIRED COMPONENTS Widgets) + set(QT_LIBRARIES Qt5::Widgets) +else() + message(FATAL_ERROR "No supported Qt version selected for build") +endif() + + include_directories(${LibCore_SOURCE_DIR}) include_directories(${LibGeometry_SOURCE_DIR}) include_directories(${LibRender_SOURCE_DIR}) @@ -17,34 +28,27 @@ include_directories(${LibViewing_SOURCE_DIR}) include_directories(${LibGuiQt_SOURCE_DIR}) set(CEE_LIBS LibGuiQt LibViewing LibRender LibGeometry LibCore) - -set(CEE_SOURCE_FILES + +set(CEE_CODE_FILES QMMain.cpp QMMainWindow.cpp +QMMainWindow.h QMWidget.cpp +QMWidget.h ) # Headers that need MOCing set(MOC_HEADER_FILES QMMainWindow.h -QMWidget.h ) -# Qt -if (CEE_USE_QT5) - find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) - qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) -else() - message(FATAL_ERROR "No supported Qt version selected for build") +if (CEE_USE_QT6) + qt_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) +elseif (CEE_USE_QT5) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) endif() -set(SYSTEM_LIBRARIES) -if (CMAKE_COMPILER_IS_GNUCXX) - set(SYSTEM_LIBRARIES -lrt -lpthread) -endif(CMAKE_COMPILER_IS_GNUCXX) - -add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${SYSTEM_LIBRARIES}) +add_executable(${PROJECT_NAME} ${CEE_CODE_FILES} ${MOC_SOURCE_FILES}) +target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMain.cpp b/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMain.cpp index c59794845c..f9ed43dfe3 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMain.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMain.cpp @@ -34,12 +34,10 @@ // //################################################################################################## - #include "cvfLibCore.h" #include "QMMainWindow.h" -#include #include #include @@ -50,6 +48,9 @@ //-------------------------------------------------------------------------------------------------- int main(int argc, char *argv[]) { + cvf::LogManager* logManager = cvf::LogManager::instance(); + logManager->logger("cee.cvf.OpenGL")->setLevel(cvf::Logger::LL_DEBUG); + QApplication app(argc, argv); // On Linux, Qt will use the system locale, force number formatting settings back to "C" locale diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMainWindow.cpp b/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMainWindow.cpp index d5fa97fe1c..f223ccac66 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMainWindow.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMainWindow.cpp @@ -34,7 +34,6 @@ // //################################################################################################## - #include "cvfLibCore.h" #include "cvfLibRender.h" #include "cvfLibGeometry.h" @@ -49,8 +48,6 @@ #include #include -using cvf::ref; - //-------------------------------------------------------------------------------------------------- @@ -63,41 +60,57 @@ QMMainWindow::QMMainWindow() setCentralWidget(mainFrame); m_contextGroup = new cvf::OpenGLContextGroup; - m_vizWidget = new QMWidget(m_contextGroup.p(), mainFrame); + + // Pass pointer to ourselves to get notified when the vizWidget is ready for use and we can load our default scene + m_vizWidget = new QMWidget(m_contextGroup.p(), mainFrame, this); m_vizWidget->setFocus(); frameLayout->addWidget(m_vizWidget); - - m_createDefaultSceneAction = new QAction("Default Scene", this); - m_clearSceneAction = new QAction("Clear Scene", this); - connect(m_createDefaultSceneAction, SIGNAL(triggered()), SLOT(slotCreateDefaultScene())); - connect(m_clearSceneAction, SIGNAL(triggered()), SLOT(slotClearScene())); - QMenu* menu = menuBar()->addMenu("&Scenes"); - menu->addAction(m_createDefaultSceneAction); + menu->addAction("Default Scene", this, SLOT(slotCreateDefaultScene())); menu->addSeparator(); - menu->addAction(m_clearSceneAction); + menu->addAction("Clear Scene", this, SLOT(slotClearScene())); +} +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMMainWindow::handleVizWidgetIsOpenGLReady() +{ slotCreateDefaultScene(); } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void QMMainWindow::slotCreateDefaultScene() { - ref model = new cvf::ModelBasicList; + cvf::ref model = new cvf::ModelBasicList; + + const bool useShaders = true; + + CVF_ASSERT(m_contextGroup->isContextGroupInitialized()); + cvf::ShaderProgramGenerator spGen("SimpleHeadlight", cvf::ShaderSourceProvider::instance()); + spGen.configureStandardHeadlightColor(); + cvf::ref shaderProg = spGen.generate(); { cvf::GeometryBuilderDrawableGeo builder; cvf::GeometryUtils::createSphere(2, 10, 10, &builder); - ref eff = new cvf::Effect; - eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::BLUE)); - - ref part = new cvf::Part; + cvf::ref eff = new cvf::Effect; + if (useShaders) + { + eff->setShaderProgram(shaderProg.p()); + eff->setUniform(new cvf::UniformFloat("u_color", cvf::Color4f(cvf::Color3::GREEN))); + } + else + { + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::BLUE)); + } + + cvf::ref part = new cvf::Part; part->setName("MySphere"); part->setDrawable(0, builder.drawableGeo().p()); part->setEffect(eff.p()); @@ -109,10 +122,18 @@ void QMMainWindow::slotCreateDefaultScene() cvf::GeometryBuilderDrawableGeo builder; cvf::GeometryUtils::createBox(cvf::Vec3f(5, 0, 0), 2, 3, 4, &builder); - ref eff = new cvf::Effect; - eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::RED)); - - ref part = new cvf::Part; + cvf::ref eff = new cvf::Effect; + if (useShaders) + { + eff->setShaderProgram(shaderProg.p()); + eff->setUniform(new cvf::UniformFloat("u_color", cvf::Color4f(cvf::Color3::YELLOW))); + } + else + { + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::RED)); + } + + cvf::ref part = new cvf::Part; part->setName("MyBox"); part->setDrawable(0, builder.drawableGeo().p()); part->setEffect(eff.p()); @@ -122,7 +143,7 @@ void QMMainWindow::slotCreateDefaultScene() model->updateBoundingBoxesRecursive(); - ref scene = new cvf::Scene; + cvf::ref scene = new cvf::Scene; scene->addModel(model.p()); CVF_ASSERT(m_vizWidget); @@ -140,15 +161,3 @@ void QMMainWindow::slotClearScene() } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -void QMMainWindow::closeEvent(QCloseEvent* /*event*/) -{ - CVF_ASSERT(m_contextGroup.notNull()); - CVF_ASSERT(m_vizWidget); - - // Shut down the CeeViz OpenGL context contained in the widget - // Deletes all OpenGL resources and removes context from context group - m_vizWidget->cvfShutdownOpenGLContext(); -} diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMainWindow.h b/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMainWindow.h index fde786d5dc..01625b7628 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMainWindow.h +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMMainWindow.h @@ -40,8 +40,8 @@ #include "cvfObject.h" #include "cvfOpenGLContextGroup.h" -#include #include +#include class QMWidget; @@ -58,17 +58,14 @@ class QMMainWindow : public QMainWindow public: QMMainWindow(); + void handleVizWidgetIsOpenGLReady(); + private slots: void slotCreateDefaultScene(); void slotClearScene(); -private: - void closeEvent(QCloseEvent* event); - private: cvf::ref m_contextGroup; - QMWidget* m_vizWidget; - QAction* m_createDefaultSceneAction; - QAction* m_clearSceneAction; + QPointer m_vizWidget; }; diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMWidget.cpp b/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMWidget.cpp index 81dbbaf395..72996cea2f 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMWidget.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMWidget.cpp @@ -34,31 +34,44 @@ // //################################################################################################## - -#include "cvfLibCore.h" -#include "cvfLibRender.h" -#include "cvfLibGeometry.h" -#include "cvfLibViewing.h" - #include "QMWidget.h" - -#include "cvfqtOpenGLContext.h" +#include "QMMainWindow.h" + +#include "cvfRendering.h" +#include "cvfRenderSequence.h" +#include "cvfScene.h" +#include "cvfCamera.h" +#include "cvfManipulatorTrackball.h" +#include "cvfOverlayAxisCross.h" +#include "cvfFixedAtlasFont.h" +#include "cvfRayIntersectSpec.h" +#include "cvfHitItemCollection.h" +#include "cvfHitItem.h" +#include "cvfTrace.h" +#include "cvfPart.h" #include -using cvf::ref; +//================================================================================================== +// +// +// +//================================================================================================== //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QMWidget::QMWidget(cvf::OpenGLContextGroup* contextGroup, QWidget* parent) -: cvfqt::OpenGLWidget(contextGroup, QGLFormat(), parent) +QMWidget::QMWidget(cvf::OpenGLContextGroup* contextGroup, QWidget* parent, QMMainWindow* mainWindow) +: cvfqt::OpenGLWidget(contextGroup, parent), + m_mainWindow(mainWindow) { + CVF_ASSERT(contextGroup); + m_camera = new cvf::Camera; - ref rendering = new cvf::Rendering; + cvf::ref rendering = new cvf::Rendering; rendering->setCamera(m_camera.p()); rendering->addOverlayItem(new cvf::OverlayAxisCross(m_camera.p(), new cvf::FixedAtlasFont(cvf::FixedAtlasFont::STANDARD))); @@ -69,7 +82,6 @@ QMWidget::QMWidget(cvf::OpenGLContextGroup* contextGroup, QWidget* parent) m_trackball->setCamera(m_camera.p()); } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -77,17 +89,15 @@ QMWidget::~QMWidget() { } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void QMWidget::setScene(cvf::Scene* scene) { - ref rendering = m_renderSequence->firstRendering(); + cvf::ref rendering = m_renderSequence->firstRendering(); CVF_ASSERT(rendering.notNull()); rendering->setScene(scene); - if (scene) { cvf::BoundingBox bb = scene->boundingBox(); @@ -101,48 +111,32 @@ void QMWidget::setScene(cvf::Scene* scene) update(); } - //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -void QMWidget::resizeGL(int width, int height) +void QMWidget::resizeGL(int w, int h) { if (m_camera.notNull()) { - m_camera->viewport()->set(0, 0, width, height); + m_camera->viewport()->set(0, 0, w, h); m_camera->setProjectionAsPerspective(m_camera->fieldOfViewYDeg(), m_camera->nearPlane(), m_camera->farPlane()); } } - //-------------------------------------------------------------------------------------------------- -/// +/// //-------------------------------------------------------------------------------------------------- -void QMWidget::paintEvent(QPaintEvent* /*event*/) +void QMWidget::paintGL() { - QPainter painter(this); - - makeCurrent(); - cvf::OpenGLContext* currentOglContext = cvfOpenGLContext(); CVF_ASSERT(currentOglContext); - CVF_CHECK_OGL(currentOglContext); - - painter.beginNativePainting(); - - cvfqt::OpenGLContext::saveOpenGLState(currentOglContext); if (m_renderSequence.notNull()) { m_renderSequence->render(currentOglContext); } - - cvfqt::OpenGLContext::restoreOpenGLState(currentOglContext); - - painter.endNativePainting(); } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -151,19 +145,24 @@ void QMWidget::mouseMoveEvent(QMouseEvent* event) if (m_renderSequence.isNull()) return; Qt::MouseButtons mouseBn = event->buttons(); - int posX = event->x(); - int posY = height() - event->y(); +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + const int posX = event->position().toPoint().x(); + const int posY = height() - event->position().toPoint().y(); +#else + const int posX = event->x(); + const int posY = height() - event->y(); +#endif cvf::ManipulatorTrackball::NavigationType navType = cvf::ManipulatorTrackball::NONE; if (mouseBn == Qt::LeftButton) { navType = cvf::ManipulatorTrackball::PAN; } - else if (mouseBn == Qt::RightButton) + else if (mouseBn == Qt::RightButton) { navType = cvf::ManipulatorTrackball::ROTATE; } - else if (mouseBn == (Qt::LeftButton | Qt::RightButton) || mouseBn == Qt::MidButton) + else if (mouseBn == (Qt::LeftButton | Qt::RightButton) || mouseBn == Qt::MiddleButton) { navType = cvf::ManipulatorTrackball::WALK; } @@ -180,7 +179,6 @@ void QMWidget::mouseMoveEvent(QMouseEvent* event) } } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -188,10 +186,19 @@ void QMWidget::mousePressEvent(QMouseEvent* event) { if (m_renderSequence.isNull()) return; - if (event->buttons() == Qt::LeftButton && event->modifiers() == Qt::ControlModifier) +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + const int posX = event->position().toPoint().x(); + const int posY = height() - event->position().toPoint().y(); +#else + const int posX = event->x(); + const int posY = height() - event->y(); +#endif + + if (event->buttons() == Qt::LeftButton && + event->modifiers() == Qt::ControlModifier) { cvf::Rendering* r = m_renderSequence->firstRendering(); - ref ris = r->rayIntersectSpecFromWindowCoordinates(event->x(), height() - event->y()); + cvf::ref ris = r->rayIntersectSpecFromWindowCoordinates(posX, posY); cvf::HitItemCollection hic; if (r->rayIntersect(*ris, &hic)) @@ -207,7 +214,6 @@ void QMWidget::mousePressEvent(QMouseEvent* event) } } - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -215,3 +221,15 @@ void QMWidget::mouseReleaseEvent(QMouseEvent* /*event*/) { m_trackball->endNavigation(); } + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget::onWidgetOpenGLReady() +{ + if (m_mainWindow) + { + m_mainWindow->handleVizWidgetIsOpenGLReady(); + } +} diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMWidget.h b/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMWidget.h index 0a789c9eb7..f1de9bdff6 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMWidget.h +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal/QMWidget.h @@ -34,7 +34,6 @@ // //################################################################################################## - #pragma once #include "cvfBase.h" @@ -46,6 +45,9 @@ #include "cvfqtOpenGLWidget.h" +#include + +class QMMainWindow; //================================================================================================== @@ -55,26 +57,27 @@ //================================================================================================== class QMWidget : public cvfqt::OpenGLWidget { - Q_OBJECT - public: - QMWidget(cvf::OpenGLContextGroup* contextGroup, QWidget* parent); + QMWidget(cvf::OpenGLContextGroup* contextGroup, QWidget* parent, QMMainWindow* mainWindow); ~QMWidget(); void setScene(cvf::Scene* scene); protected: - void resizeGL(int width, int height); - void paintEvent(QPaintEvent *event); + virtual void resizeGL(int w, int h); + virtual void paintGL(); - void mousePressEvent(QMouseEvent* event); - void mouseMoveEvent(QMouseEvent* event); - void mouseReleaseEvent(QMouseEvent* event); + virtual void mouseMoveEvent(QMouseEvent* event); + virtual void mousePressEvent(QMouseEvent* event); + virtual void mouseReleaseEvent(QMouseEvent* event); private: + virtual void onWidgetOpenGLReady(); + +private: + QPointer m_mainWindow; cvf::ref m_renderSequence; cvf::ref m_camera; cvf::ref m_trackball; }; - diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/CMakeLists.txt new file mode 100644 index 0000000000..9ce977557a --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/CMakeLists.txt @@ -0,0 +1,47 @@ +project(QtMinimal_GLWidget) + + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STANDARD_CXX_FLAGS}") + +if (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long") +endif() + + +find_package(OpenGL) + +if (CEE_USE_QT5) + find_package(Qt5 REQUIRED COMPONENTS Widgets OpenGL) + set(QT_LIBRARIES Qt5::Widgets Qt5::OpenGL) +else() + message(FATAL_ERROR "No supported Qt version selected for build") +endif() + + +include_directories(${LibCore_SOURCE_DIR}) +include_directories(${LibGeometry_SOURCE_DIR}) +include_directories(${LibRender_SOURCE_DIR}) +include_directories(${LibViewing_SOURCE_DIR}) +include_directories(${LibGuiQt_SOURCE_DIR}) + +set(CEE_LIBS LibGuiQt LibViewing LibRender LibGeometry LibCore) + + +set(CEE_SOURCE_FILES +QMMain_GLW.cpp +QMMainWindow_GLW.cpp +QMWidget_GLW.cpp +) + +# Headers that need MOCing +set(MOC_HEADER_FILES +QMMainWindow_GLW.h +QMWidget_GLW.h +) + +if (CEE_USE_QT5) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) +endif() + +add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) +target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMMainWindow_GLW.cpp b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMMainWindow_GLW.cpp new file mode 100644 index 0000000000..b9d687f7b6 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMMainWindow_GLW.cpp @@ -0,0 +1,153 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#include "cvfLibCore.h" +#include "cvfLibRender.h" +#include "cvfLibGeometry.h" +#include "cvfLibViewing.h" + +#include "QMMainWindow_GLW.h" +#include "QMWidget_GLW.h" + +#include +#include +#include +#include +#include + +using cvf::ref; + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMMainWindow_GLW::QMMainWindow_GLW() +{ + QFrame* mainFrame = new QFrame; + QHBoxLayout* frameLayout = new QHBoxLayout(mainFrame); + setCentralWidget(mainFrame); + + m_contextGroup = new cvf::OpenGLContextGroup; + m_vizWidget = new QMWidget_GLW(m_contextGroup.p(), mainFrame); + + m_vizWidget->setFocus(); + frameLayout->addWidget(m_vizWidget); + + + m_createDefaultSceneAction = new QAction("Default Scene", this); + m_clearSceneAction = new QAction("Clear Scene", this); + connect(m_createDefaultSceneAction, SIGNAL(triggered()), SLOT(slotCreateDefaultScene())); + connect(m_clearSceneAction, SIGNAL(triggered()), SLOT(slotClearScene())); + + QMenu* menu = menuBar()->addMenu("&Scenes"); + menu->addAction(m_createDefaultSceneAction); + menu->addSeparator(); + menu->addAction(m_clearSceneAction); + + slotCreateDefaultScene(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMMainWindow_GLW::slotCreateDefaultScene() +{ + ref model = new cvf::ModelBasicList; + + { + cvf::GeometryBuilderDrawableGeo builder; + cvf::GeometryUtils::createSphere(2, 10, 10, &builder); + + ref eff = new cvf::Effect; + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::BLUE)); + + ref part = new cvf::Part; + part->setName("MySphere"); + part->setDrawable(0, builder.drawableGeo().p()); + part->setEffect(eff.p()); + + model->addPart(part.p()); + } + + { + cvf::GeometryBuilderDrawableGeo builder; + cvf::GeometryUtils::createBox(cvf::Vec3f(5, 0, 0), 2, 3, 4, &builder); + + ref eff = new cvf::Effect; + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::RED)); + + ref part = new cvf::Part; + part->setName("MyBox"); + part->setDrawable(0, builder.drawableGeo().p()); + part->setEffect(eff.p()); + + model->addPart(part.p()); + } + + model->updateBoundingBoxesRecursive(); + + ref scene = new cvf::Scene; + scene->addModel(model.p()); + + CVF_ASSERT(m_vizWidget); + m_vizWidget->setScene(scene.p()); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMMainWindow_GLW::slotClearScene() +{ + CVF_ASSERT(m_vizWidget); + m_vizWidget->setScene(NULL); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMMainWindow_GLW::closeEvent(QCloseEvent* /*event*/) +{ + CVF_ASSERT(m_contextGroup.notNull()); + CVF_ASSERT(m_vizWidget); + + // Shut down the CeeViz OpenGL context contained in the widget + // Deletes all OpenGL resources and removes context from context group + m_vizWidget->cvfShutdownOpenGLContext(); +} diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMMainWindow_GLW.h b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMMainWindow_GLW.h new file mode 100644 index 0000000000..d337ec92d4 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMMainWindow_GLW.h @@ -0,0 +1,73 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfOpenGLContextGroup.h" + +#include + +class QMWidget_GLW; + + +//================================================================================================== +// +// +// +//================================================================================================== +class QMMainWindow_GLW : public QMainWindow +{ + Q_OBJECT + +public: + QMMainWindow_GLW(); + +private slots: + void slotCreateDefaultScene(); + void slotClearScene(); + +private: + void closeEvent(QCloseEvent* event); + +private: + cvf::ref m_contextGroup; + QMWidget_GLW* m_vizWidget; + QAction* m_createDefaultSceneAction; + QAction* m_clearSceneAction; +}; + diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMMain_GLW.cpp b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMMain_GLW.cpp new file mode 100644 index 0000000000..2d9e6fe26a --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMMain_GLW.cpp @@ -0,0 +1,63 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#include "cvfLibCore.h" + +#include "QMMainWindow_GLW.h" + +#include "QApplication" + +#include + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + // On Linux, Qt will use the system locale, force number formatting settings back to "C" locale + setlocale(LC_NUMERIC,"C"); + + QMMainWindow_GLW window; + QString platform = cvf::System::is64Bit() ? "(64bit)" : "(32bit)"; + window.setWindowTitle("Qt Minimal GLWidget " + platform); + window.resize(1000, 800);; + window.show(); + + return app.exec(); +} diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMWidget_GLW.cpp b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMWidget_GLW.cpp new file mode 100644 index 0000000000..7f6dd48cec --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMWidget_GLW.cpp @@ -0,0 +1,215 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#include "cvfLibCore.h" +#include "cvfLibRender.h" +#include "cvfLibGeometry.h" +#include "cvfLibViewing.h" + +#include "QMWidget_GLW.h" + +#include + +using cvf::ref; + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMWidget_GLW::QMWidget_GLW(cvf::OpenGLContextGroup* contextGroup, QWidget* parent) +: cvfqt::GLWidget(contextGroup, QGLFormat(), parent) +{ + m_camera = new cvf::Camera; + + ref rendering = new cvf::Rendering; + rendering->setCamera(m_camera.p()); + rendering->addOverlayItem(new cvf::OverlayAxisCross(m_camera.p(), new cvf::FixedAtlasFont(cvf::FixedAtlasFont::STANDARD))); + + m_renderSequence = new cvf::RenderSequence; + m_renderSequence->addRendering(rendering.p()); + + m_trackball = new cvf::ManipulatorTrackball; + m_trackball->setCamera(m_camera.p()); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMWidget_GLW::~QMWidget_GLW() +{ +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_GLW::setScene(cvf::Scene* scene) +{ + ref rendering = m_renderSequence->firstRendering(); + CVF_ASSERT(rendering.notNull()); + + rendering->setScene(scene); + + if (scene) + { + cvf::BoundingBox bb = scene->boundingBox(); + if (bb.isValid()) + { + m_camera->fitView(bb, -cvf::Vec3d::Z_AXIS, cvf::Vec3d::Y_AXIS); + m_trackball->setRotationPoint(bb.center()); + } + } + + update(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_GLW::resizeGL(int width, int height) +{ + if (m_camera.notNull()) + { + m_camera->viewport()->set(0, 0, width, height); + m_camera->setProjectionAsPerspective(m_camera->fieldOfViewYDeg(), m_camera->nearPlane(), m_camera->farPlane()); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_GLW::paintEvent(QPaintEvent* /*event*/) +{ + QPainter painter(this); + + makeCurrent(); + + cvf::OpenGLContext* currentOglContext = cvfOpenGLContext(); + CVF_ASSERT(currentOglContext); + CVF_CHECK_OGL(currentOglContext); + + painter.beginNativePainting(); + + cvf::OpenGLUtils::pushOpenGLState(currentOglContext); + + if (m_renderSequence.notNull()) + { + m_renderSequence->render(currentOglContext); + } + + cvf::OpenGLUtils::popOpenGLState(currentOglContext); + + painter.endNativePainting(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_GLW::mouseMoveEvent(QMouseEvent* event) +{ + if (m_renderSequence.isNull()) return; + + Qt::MouseButtons mouseBn = event->buttons(); + int posX = event->x(); + int posY = height() - event->y(); + + cvf::ManipulatorTrackball::NavigationType navType = cvf::ManipulatorTrackball::NONE; + if (mouseBn == Qt::LeftButton) + { + navType = cvf::ManipulatorTrackball::PAN; + } + else if (mouseBn == Qt::RightButton) + { + navType = cvf::ManipulatorTrackball::ROTATE; + } + else if (mouseBn == (Qt::LeftButton | Qt::RightButton) || mouseBn == Qt::MiddleButton) + { + navType = cvf::ManipulatorTrackball::WALK; + } + + if (navType != m_trackball->activeNavigation()) + { + m_trackball->startNavigation(navType, posX, posY); + } + + bool needRedraw = m_trackball->updateNavigation(posX, posY); + if (needRedraw) + { + update(); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_GLW::mousePressEvent(QMouseEvent* event) +{ + if (m_renderSequence.isNull()) return; + + if (event->buttons() == Qt::LeftButton && event->modifiers() == Qt::ControlModifier) + { + cvf::Rendering* r = m_renderSequence->firstRendering(); + ref ris = r->rayIntersectSpecFromWindowCoordinates(event->x(), height() - event->y()); + + cvf::HitItemCollection hic; + if (r->rayIntersect(*ris, &hic)) + { + cvf::HitItem* item = hic.firstItem(); + CVF_ASSERT(item && item->part()); + + cvf::Vec3d isect = item->intersectionPoint(); + m_trackball->setRotationPoint(isect); + + cvf::Trace::show("hitting part: '%s' coords: %.3f %.3f %.3f", item->part()->name().toAscii().ptr(), isect.x(), isect.y(), isect.z()); + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_GLW::mouseReleaseEvent(QMouseEvent* /*event*/) +{ + m_trackball->endNavigation(); +} + diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMWidget_GLW.h b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMWidget_GLW.h new file mode 100644 index 0000000000..6913faf9aa --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_GLWidget/QMWidget_GLW.h @@ -0,0 +1,79 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfRenderSequence.h" +#include "cvfManipulatorTrackball.h" +#include "cvfScene.h" +#include "cvfOpenGLContextGroup.h" + +#include "cvfqtGLWidget.h" + + + +//================================================================================================== +// +// +// +//================================================================================================== +class QMWidget_GLW : public cvfqt::GLWidget +{ + Q_OBJECT + +public: + QMWidget_GLW(cvf::OpenGLContextGroup* contextGroup, QWidget* parent); + ~QMWidget_GLW(); + + void setScene(cvf::Scene* scene); + +protected: + void resizeGL(int width, int height); + void paintEvent(QPaintEvent *event); + + void mousePressEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); + +private: + cvf::ref m_renderSequence; + cvf::ref m_camera; + cvf::ref m_trackball; +}; + + diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/CMakeLists.txt new file mode 100644 index 0000000000..bee5f07910 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/CMakeLists.txt @@ -0,0 +1,50 @@ +project(QtMinimal_deprecated) + + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_BASE_CXX_FLAGS}") + +if (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long") +endif() + + +find_package(OpenGL) + +include_directories(${LibCore_SOURCE_DIR}) +include_directories(${LibGeometry_SOURCE_DIR}) +include_directories(${LibRender_SOURCE_DIR}) +include_directories(${LibViewing_SOURCE_DIR}) +include_directories(${LibGuiQt_SOURCE_DIR}) + +set(CEE_LIBS LibGuiQt LibViewing LibRender LibGeometry LibCore) + + +set(CEE_SOURCE_FILES +QMMain_deprecated.cpp +QMMainWindow_deprecated.cpp +QMWidget_deprecated.cpp +) + +# Headers that need MOCing +set(MOC_HEADER_FILES +QMMainWindow_deprecated.h +QMWidget_deprecated.h +) + +# Qt +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) +else() + message(FATAL_ERROR "No supported Qt version selected for build") +endif() + +set(SYSTEM_LIBRARIES) +if (CMAKE_COMPILER_IS_GNUCXX) + set(SYSTEM_LIBRARIES -lrt -lpthread) +endif(CMAKE_COMPILER_IS_GNUCXX) + +add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) +target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${SYSTEM_LIBRARIES}) + diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMMainWindow_deprecated.cpp b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMMainWindow_deprecated.cpp new file mode 100644 index 0000000000..16fa6a8007 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMMainWindow_deprecated.cpp @@ -0,0 +1,154 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#include "cvfLibCore.h" +#include "cvfLibRender.h" +#include "cvfLibGeometry.h" +#include "cvfLibViewing.h" + +#include "QMMainWindow_deprecated.h" +#include "QMWidget_deprecated.h" + +#include +#include +#include +#include +#include + +using cvf::ref; + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMMainWindow_deprecated::QMMainWindow_deprecated() +{ + QFrame* mainFrame = new QFrame; + QHBoxLayout* frameLayout = new QHBoxLayout(mainFrame); + setCentralWidget(mainFrame); + + m_contextGroup = new cvf::OpenGLContextGroup; + m_vizWidget = new QMWidget_deprecated(m_contextGroup.p(), mainFrame); + + m_vizWidget->setFocus(); + frameLayout->addWidget(m_vizWidget); + + + m_createDefaultSceneAction = new QAction("Default Scene", this); + m_clearSceneAction = new QAction("Clear Scene", this); + connect(m_createDefaultSceneAction, SIGNAL(triggered()), SLOT(slotCreateDefaultScene())); + connect(m_clearSceneAction, SIGNAL(triggered()), SLOT(slotClearScene())); + + QMenu* menu = menuBar()->addMenu("&Scenes"); + menu->addAction(m_createDefaultSceneAction); + menu->addSeparator(); + menu->addAction(m_clearSceneAction); + + slotCreateDefaultScene(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMMainWindow_deprecated::slotCreateDefaultScene() +{ + ref model = new cvf::ModelBasicList; + + { + cvf::GeometryBuilderDrawableGeo builder; + cvf::GeometryUtils::createSphere(2, 10, 10, &builder); + + ref eff = new cvf::Effect; + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::BLUE)); + + ref part = new cvf::Part; + part->setName("MySphere"); + part->setDrawable(0, builder.drawableGeo().p()); + part->setEffect(eff.p()); + + model->addPart(part.p()); + } + + { + cvf::GeometryBuilderDrawableGeo builder; + cvf::GeometryUtils::createBox(cvf::Vec3f(5, 0, 0), 2, 3, 4, &builder); + + ref eff = new cvf::Effect; + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::RED)); + + ref part = new cvf::Part; + part->setName("MyBox"); + part->setDrawable(0, builder.drawableGeo().p()); + part->setEffect(eff.p()); + + model->addPart(part.p()); + } + + model->updateBoundingBoxesRecursive(); + + ref scene = new cvf::Scene; + scene->addModel(model.p()); + + CVF_ASSERT(m_vizWidget); + m_vizWidget->setScene(scene.p()); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMMainWindow_deprecated::slotClearScene() +{ + CVF_ASSERT(m_vizWidget); + m_vizWidget->setScene(NULL); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMMainWindow_deprecated::closeEvent(QCloseEvent* /*event*/) +{ + CVF_ASSERT(m_contextGroup.notNull()); + CVF_ASSERT(m_vizWidget); + + // Shut down the CeeViz OpenGL context contained in the widget + // Deletes all OpenGL resources and removes context from context group + m_vizWidget->cvfShutdownOpenGLContext(); +} diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMMainWindow_deprecated.h b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMMainWindow_deprecated.h new file mode 100644 index 0000000000..8ee07b3fe4 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMMainWindow_deprecated.h @@ -0,0 +1,74 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfOpenGLContextGroup.h" + +#include +#include + +class QMWidget_deprecated; + + +//================================================================================================== +// +// +// +//================================================================================================== +class QMMainWindow_deprecated : public QMainWindow +{ + Q_OBJECT + +public: + QMMainWindow_deprecated(); + +private slots: + void slotCreateDefaultScene(); + void slotClearScene(); + +private: + void closeEvent(QCloseEvent* event); + +private: + cvf::ref m_contextGroup; + QMWidget_deprecated* m_vizWidget; + QAction* m_createDefaultSceneAction; + QAction* m_clearSceneAction; +}; + diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMMain_deprecated.cpp b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMMain_deprecated.cpp new file mode 100644 index 0000000000..2040cda55c --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMMain_deprecated.cpp @@ -0,0 +1,65 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#include "cvfLibCore.h" + +#include "QMMainWindow_deprecated.h" + +#include +#include + +#include + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + // On Linux, Qt will use the system locale, force number formatting settings back to "C" locale + setlocale(LC_NUMERIC,"C"); + + QMMainWindow_deprecated window; + QString platform = cvf::System::is64Bit() ? "(64bit)" : "(32bit)"; + window.setWindowTitle("Qt Minimal deprecated" + platform); + window.resize(1000, 800);; + window.show(); + + return app.exec(); +} diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMWidget_deprecated.cpp b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMWidget_deprecated.cpp new file mode 100644 index 0000000000..979f4856d6 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMWidget_deprecated.cpp @@ -0,0 +1,215 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#include "cvfLibCore.h" +#include "cvfLibRender.h" +#include "cvfLibGeometry.h" +#include "cvfLibViewing.h" + +#include "QMWidget_deprecated.h" + +#include + +using cvf::ref; + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMWidget_deprecated::QMWidget_deprecated(cvf::OpenGLContextGroup* contextGroup, QWidget* parent) +: cvfqt::GLWidget_deprecated(contextGroup, QGLFormat(), parent) +{ + m_camera = new cvf::Camera; + + ref rendering = new cvf::Rendering; + rendering->setCamera(m_camera.p()); + rendering->addOverlayItem(new cvf::OverlayAxisCross(m_camera.p(), new cvf::FixedAtlasFont(cvf::FixedAtlasFont::STANDARD))); + + m_renderSequence = new cvf::RenderSequence; + m_renderSequence->addRendering(rendering.p()); + + m_trackball = new cvf::ManipulatorTrackball; + m_trackball->setCamera(m_camera.p()); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMWidget_deprecated::~QMWidget_deprecated() +{ +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_deprecated::setScene(cvf::Scene* scene) +{ + ref rendering = m_renderSequence->firstRendering(); + CVF_ASSERT(rendering.notNull()); + + rendering->setScene(scene); + + if (scene) + { + cvf::BoundingBox bb = scene->boundingBox(); + if (bb.isValid()) + { + m_camera->fitView(bb, -cvf::Vec3d::Z_AXIS, cvf::Vec3d::Y_AXIS); + m_trackball->setRotationPoint(bb.center()); + } + } + + update(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_deprecated::resizeGL(int width, int height) +{ + if (m_camera.notNull()) + { + m_camera->viewport()->set(0, 0, width, height); + m_camera->setProjectionAsPerspective(m_camera->fieldOfViewYDeg(), m_camera->nearPlane(), m_camera->farPlane()); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_deprecated::paintEvent(QPaintEvent* /*event*/) +{ + QPainter painter(this); + + makeCurrent(); + + cvf::OpenGLContext* currentOglContext = cvfOpenGLContext(); + CVF_ASSERT(currentOglContext); + CVF_CHECK_OGL(currentOglContext); + + painter.beginNativePainting(); + + cvf::OpenGLUtils::pushOpenGLState(currentOglContext); + + if (m_renderSequence.notNull()) + { + m_renderSequence->render(currentOglContext); + } + + cvf::OpenGLUtils::popOpenGLState(currentOglContext); + + painter.endNativePainting(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_deprecated::mouseMoveEvent(QMouseEvent* event) +{ + if (m_renderSequence.isNull()) return; + + Qt::MouseButtons mouseBn = event->buttons(); + int posX = event->x(); + int posY = height() - event->y(); + + cvf::ManipulatorTrackball::NavigationType navType = cvf::ManipulatorTrackball::NONE; + if (mouseBn == Qt::LeftButton) + { + navType = cvf::ManipulatorTrackball::PAN; + } + else if (mouseBn == Qt::RightButton) + { + navType = cvf::ManipulatorTrackball::ROTATE; + } + else if (mouseBn == (Qt::LeftButton | Qt::RightButton) || mouseBn == Qt::MiddleButton) + { + navType = cvf::ManipulatorTrackball::WALK; + } + + if (navType != m_trackball->activeNavigation()) + { + m_trackball->startNavigation(navType, posX, posY); + } + + bool needRedraw = m_trackball->updateNavigation(posX, posY); + if (needRedraw) + { + update(); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_deprecated::mousePressEvent(QMouseEvent* event) +{ + if (m_renderSequence.isNull()) return; + + if (event->buttons() == Qt::LeftButton && event->modifiers() == Qt::ControlModifier) + { + cvf::Rendering* r = m_renderSequence->firstRendering(); + ref ris = r->rayIntersectSpecFromWindowCoordinates(event->x(), height() - event->y()); + + cvf::HitItemCollection hic; + if (r->rayIntersect(*ris, &hic)) + { + cvf::HitItem* item = hic.firstItem(); + CVF_ASSERT(item && item->part()); + + cvf::Vec3d isect = item->intersectionPoint(); + m_trackball->setRotationPoint(isect); + + cvf::Trace::show("hitting part: '%s' coords: %.3f %.3f %.3f", item->part()->name().toAscii().ptr(), isect.x(), isect.y(), isect.z()); + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMWidget_deprecated::mouseReleaseEvent(QMouseEvent* /*event*/) +{ + m_trackball->endNavigation(); +} diff --git a/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMWidget_deprecated.h b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMWidget_deprecated.h new file mode 100644 index 0000000000..5d4f95c51b --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMinimal_deprecated/QMWidget_deprecated.h @@ -0,0 +1,80 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfRenderSequence.h" +#include "cvfManipulatorTrackball.h" +#include "cvfScene.h" +#include "cvfOpenGLContextGroup.h" + +#include "cvfqtGLWidget_deprecated.h" + + + +//================================================================================================== +// +// +// +//================================================================================================== +class QMWidget_deprecated : public cvfqt::GLWidget_deprecated +{ + Q_OBJECT + +public: + QMWidget_deprecated(cvf::OpenGLContextGroup* contextGroup, QWidget* parent); + ~QMWidget_deprecated(); + + void setScene(cvf::Scene* scene); + +protected: + void resizeGL(int width, int height); + void paintEvent(QPaintEvent *event); + + void mousePressEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); + +private: + cvf::ref m_renderSequence; + cvf::ref m_camera; + cvf::ref m_trackball; +}; + + diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt index c450a3a9f2..93bf747943 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView/CMakeLists.txt @@ -1,7 +1,7 @@ project(QtMultiView) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_BASE_CXX_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STANDARD_CXX_FLAGS}") if (CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long") @@ -10,21 +10,35 @@ endif() find_package(OpenGL) +if (CEE_USE_QT6) + find_package(Qt6 COMPONENTS REQUIRED OpenGLWidgets) + set(QT_LIBRARIES Qt6::OpenGLWidgets ) +elseif (CEE_USE_QT5) + find_package(Qt5 REQUIRED COMPONENTS Widgets) + set(QT_LIBRARIES Qt5::Widgets) +else() + message(FATAL_ERROR "No supported Qt version selected for build") +endif() + + include_directories(${LibCore_SOURCE_DIR}) include_directories(${LibGeometry_SOURCE_DIR}) include_directories(${LibRender_SOURCE_DIR}) include_directories(${LibViewing_SOURCE_DIR}) -include_directories(${LibGuiQt_SOURCE_DIR}) include_directories(${LibUtilities_SOURCE_DIR}) +include_directories(${LibGuiQt_SOURCE_DIR}) -set(CEE_LIBS LibUtilities LibGuiQt LibViewing LibRender LibGeometry LibIo LibCore) -set(EXTERNAL_LIBS) +set(CEE_LIBS LibGuiQt LibUtilities LibViewing LibRender LibGeometry LibIo LibCore) -set(CEE_SOURCE_FILES + +set(CEE_CODE_FILES QMVFactory.cpp +QMVFactory.h QMVMain.cpp QMVMainWindow.cpp +QMVMainWindow.h QMVWidget.cpp +QMVWidget.h ) # Headers that need MOCing @@ -33,19 +47,12 @@ QMVMainWindow.h QMVWidget.h ) -# Qt -if (CEE_USE_QT5) - find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) - set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) - qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) -else() - message(FATAL_ERROR "No supported Qt version selected for build") +if (CEE_USE_QT6) + qt_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) +elseif (CEE_USE_QT5) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) endif() -set(SYSTEM_LIBRARIES) -if (CMAKE_COMPILER_IS_GNUCXX) - set(SYSTEM_LIBRARIES -lrt -lpthread) -endif(CMAKE_COMPILER_IS_GNUCXX) +add_executable(${PROJECT_NAME} ${CEE_CODE_FILES} ${MOC_SOURCE_FILES}) +target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) -add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) -target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${SYSTEM_LIBRARIES}) diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVFactory.cpp b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVFactory.cpp index 802687dccf..e60d728a25 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVFactory.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVFactory.cpp @@ -34,7 +34,6 @@ // //################################################################################################## - #include "cvfLibCore.h" #include "cvfLibRender.h" #include "cvfLibGeometry.h" @@ -46,7 +45,6 @@ - //================================================================================================== // // @@ -56,8 +54,9 @@ //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QMVModelFactory::QMVModelFactory(bool useShaders) -: m_useShaders(useShaders) +QMVModelFactory::QMVModelFactory(bool useShaders, const cvf::OpenGLCapabilities& capabilities) +: m_useShaders(useShaders), + m_capabilities(capabilities) { } @@ -65,24 +64,27 @@ QMVModelFactory::QMVModelFactory(bool useShaders) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -ref QMVModelFactory::createSphereAndBox() +cvf::ref QMVModelFactory::createSphereAndBox() { - ref model = new cvf::ModelBasicList; + cvf::ref model = new cvf::ModelBasicList; { cvf::GeometryBuilderDrawableGeo builder; cvf::GeometryUtils::createSphere(2, 10, 10, &builder); - ref eff = new cvf::Effect; - eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::BLUE)); + cvf::ref eff = new cvf::Effect; if (m_useShaders) { - ref prog = createProgramStandardHeadlightColor(); + cvf::ref prog = createProgramStandardHeadlightColor(); eff->setShaderProgram(prog.p()); eff->setUniform(new cvf::UniformFloat("u_color", cvf::Color4f(cvf::Color3::GREEN))); } + else + { + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::BLUE)); + } - ref part = new cvf::Part; + cvf::ref part = new cvf::Part; part->setName("MySphere"); part->setDrawable(0, builder.drawableGeo().p()); part->setEffect(eff.p()); @@ -94,16 +96,19 @@ ref QMVModelFactory::createSphereAndBox() cvf::GeometryBuilderDrawableGeo builder; cvf::GeometryUtils::createBox(cvf::Vec3f(5, 0, 0), 2, 3, 4, &builder); - ref eff = new cvf::Effect; - eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::RED)); + cvf::ref eff = new cvf::Effect; if (m_useShaders) { - ref prog = createProgramUnlit(); + cvf::ref prog = createProgramUnlit(); eff->setShaderProgram(prog.p()); eff->setUniform(new cvf::UniformFloat("u_color", cvf::Color4f(cvf::Color3::GREEN))); } + else + { + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::RED)); + } - ref part = new cvf::Part; + cvf::ref part = new cvf::Part; part->setName("MyBox"); part->setDrawable(0, builder.drawableGeo().p()); part->setEffect(eff.p()); @@ -120,9 +125,10 @@ ref QMVModelFactory::createSphereAndBox() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -ref QMVModelFactory::createSpheres() +cvf::ref QMVModelFactory::createSpheres() { cvfu::PartCompoundGenerator gen; + gen.setUseShaders(m_useShaders); gen.setPartDistribution(cvf::Vec3i(5, 5, 5)); gen.setNumEffects(8); gen.useRandomEffectAssignment(false); @@ -132,9 +138,9 @@ ref QMVModelFactory::createSpheres() cvf::Collection parts; gen.generateSpheres(20, 20, &parts); - ref model = new cvf::ModelBasicList; + cvf::ref model = new cvf::ModelBasicList; - ref prog = createProgramStandardHeadlightColor(); + cvf::ref prog = createProgramStandardHeadlightColor(); size_t i; for (i = 0; i < parts.size(); i++) @@ -158,9 +164,10 @@ ref QMVModelFactory::createSpheres() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -ref QMVModelFactory::createBoxes() +cvf::ref QMVModelFactory::createBoxes() { cvfu::PartCompoundGenerator gen; + gen.setUseShaders(m_useShaders); gen.setPartDistribution(cvf::Vec3i(5, 5, 5)); gen.setNumEffects(8); gen.useRandomEffectAssignment(false); @@ -170,9 +177,9 @@ ref QMVModelFactory::createBoxes() cvf::Collection parts; gen.generateBoxes(&parts); - ref model = new cvf::ModelBasicList; + cvf::ref model = new cvf::ModelBasicList; - ref prog = createProgramStandardHeadlightColor(); + cvf::ref prog = createProgramStandardHeadlightColor(); size_t i; for (i = 0; i < parts.size(); i++) @@ -196,9 +203,10 @@ ref QMVModelFactory::createBoxes() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -ref QMVModelFactory::createTriangles() +cvf::ref QMVModelFactory::createTriangles() { cvfu::PartCompoundGenerator gen; + gen.setUseShaders(m_useShaders); gen.setPartDistribution(cvf::Vec3i(5, 5, 5)); gen.setNumEffects(8); gen.useRandomEffectAssignment(false); @@ -208,9 +216,9 @@ ref QMVModelFactory::createTriangles() cvf::Collection parts; gen.generateTriangles(&parts); - ref model = new cvf::ModelBasicList; + cvf::ref model = new cvf::ModelBasicList; - ref prog = createProgramStandardHeadlightColor(); + cvf::ref prog = createProgramStandardHeadlightColor(); size_t i; for (i = 0; i < parts.size(); i++) @@ -234,11 +242,11 @@ ref QMVModelFactory::createTriangles() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -ref QMVModelFactory::createProgramStandardHeadlightColor() +cvf::ref QMVModelFactory::createProgramStandardHeadlightColor() { cvf::ShaderProgramGenerator gen("StandardHeadlightColor", cvf::ShaderSourceProvider::instance()); gen.configureStandardHeadlightColor(); - ref prog = gen.generate(); + cvf::ref prog = gen.generate(); return prog; } @@ -246,13 +254,13 @@ ref QMVModelFactory::createProgramStandardHeadlightColor() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -ref QMVModelFactory::createProgramUnlit() +cvf::ref QMVModelFactory::createProgramUnlit() { cvf::ShaderProgramGenerator gen("Unlit", cvf::ShaderSourceProvider::instance()); gen.addVertexCode(cvf::ShaderSourceRepository::vs_Standard); gen.addFragmentCode(cvf::ShaderSourceRepository::src_Color); gen.addFragmentCode(cvf::ShaderSourceRepository::fs_Unlit); - ref prog = gen.generate(); + cvf::ref prog = gen.generate(); return prog; } @@ -275,9 +283,9 @@ QMVSceneFactory::QMVSceneFactory(QMVModelFactory* modelFactory) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -ref QMVSceneFactory::createNumberedScene(int sceneNumber) +cvf::ref QMVSceneFactory::createNumberedScene(int sceneNumber) { - ref model; + cvf::ref model; switch (sceneNumber) { case 0: model = m_modelFactory->createSphereAndBox(); break; @@ -293,9 +301,9 @@ ref QMVSceneFactory::createNumberedScene(int sceneNumber) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -ref QMVSceneFactory::createFromModel(cvf::Model* model) +cvf::ref QMVSceneFactory::createFromModel(cvf::Model* model) { - ref scene = new cvf::Scene; + cvf::ref scene = new cvf::Scene; if (model) { @@ -316,9 +324,9 @@ ref QMVSceneFactory::createFromModel(cvf::Model* model) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -ref QMVRenderSequenceFactory::createFromScene(cvf::Scene* scene) +cvf::ref QMVRenderSequenceFactory::createFromScene(cvf::Scene* scene) { - ref rendering = new cvf::Rendering; + cvf::ref rendering = new cvf::Rendering; rendering->renderEngine()->enableItemCountUpdate(true); rendering->setScene(scene); @@ -334,7 +342,7 @@ ref QMVRenderSequenceFactory::createFromScene(cvf::Scene* s } } - ref renderSeq = new cvf::RenderSequence; + cvf::ref renderSeq = new cvf::RenderSequence; renderSeq->addRendering(rendering.p()); return renderSeq; diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVFactory.h b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVFactory.h index d4fcc7e96b..c835edce2f 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVFactory.h +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVFactory.h @@ -34,10 +34,8 @@ // //################################################################################################## - #pragma once -using cvf::ref; //================================================================================================== @@ -48,19 +46,20 @@ using cvf::ref; class QMVModelFactory { public: - QMVModelFactory(bool useShaders); + QMVModelFactory(bool useShaders, const cvf::OpenGLCapabilities& capabilities); - ref createSphereAndBox(); - ref createSpheres(); - ref createBoxes(); - ref createTriangles(); + cvf::ref createSphereAndBox(); + cvf::ref createSpheres(); + cvf::ref createBoxes(); + cvf::ref createTriangles(); private: - ref createProgramStandardHeadlightColor(); - ref createProgramUnlit(); + cvf::ref createProgramStandardHeadlightColor(); + cvf::ref createProgramUnlit(); private: bool m_useShaders; + cvf::OpenGLCapabilities m_capabilities; }; @@ -75,8 +74,8 @@ class QMVSceneFactory public: QMVSceneFactory(QMVModelFactory* modelFactory); - ref createNumberedScene(int sceneNumber); - ref createFromModel(cvf::Model* model); + cvf::ref createNumberedScene(int sceneNumber); + cvf::ref createFromModel(cvf::Model* model); private: QMVModelFactory* m_modelFactory; @@ -92,6 +91,6 @@ class QMVSceneFactory class QMVRenderSequenceFactory { public: - ref createFromScene(cvf::Scene* model); + cvf::ref createFromScene(cvf::Scene* model); }; diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMain.cpp b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMain.cpp index 0cc057ca44..dd1f7d0262 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMain.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMain.cpp @@ -34,15 +34,14 @@ // //################################################################################################## - #include "cvfLibCore.h" #include "QMVMainWindow.h" #include -#include "QtOpenGL/qgl.h" -#include +#include + //-------------------------------------------------------------------------------------------------- @@ -50,19 +49,30 @@ //-------------------------------------------------------------------------------------------------- int main(int argc, char *argv[]) { - // It seems that if we are using paintEvent() instead of paintGL() to - // draw we might have to set OpenGL as the preferred paint engine - //QGL::setPreferredPaintEngine(QPaintEngine::OpenGL); + // Enables resource sharing between QOpenGLWidget instances that belong to different top-level windows + // Must be enabled if we want to create multiple OpenGL widgets in the same context group and they're not sitting as direct children of the same widget. + // Enable here so we can experiment with creating widgets as floating dialogs + QApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + + // Can be used as a work-around if OpenGL scene appears as black in combination with remote desktop for Win7 clients + // See: https://bugreports.qt.io/browse/QTBUG-47975 + //QSurfaceFormat surface; + //surface.setAlphaBufferSize(8); + //QSurfaceFormat::setDefaultFormat(surface); + QApplication app(argc, argv); + cvf::LogManager* logManager = cvf::LogManager::instance(); + logManager->logger("cee.cvf.OpenGL")->setLevel(4); + // On Linux, Qt will use the system locale, force number formatting settings back to "C" locale setlocale(LC_NUMERIC,"C"); QMVMainWindow window; QString platform = cvf::System::is64Bit() ? "(64bit)" : "(32bit)"; window.setWindowTitle("Qt MultiView " + platform); - window.resize(1000, 800);; + window.resize(1000, 800); window.show(); return app.exec(); diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMainWindow.cpp b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMainWindow.cpp index 75b23cda1b..5b70c01d33 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMainWindow.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMainWindow.cpp @@ -34,7 +34,6 @@ // //################################################################################################## - #include "cvfLibCore.h" #include "cvfLibRender.h" #include "cvfLibGeometry.h" @@ -53,8 +52,6 @@ #include #include -using cvf::ref; - //-------------------------------------------------------------------------------------------------- @@ -70,98 +67,72 @@ QMVMainWindow::QMVMainWindow() setCentralWidget(mainFrame); + QMenu* widgetsMenu = menuBar()->addMenu("&Widgets"); + + m_createWidgetsAsFloatingDialogsAction = new QAction("Create Widgets as Floating Dialogs", this); + m_createWidgetsAsFloatingDialogsAction->setCheckable(true); + m_recycleScenesInWidgetConfigAction = new QAction("Recycle Scenes When Changing Widget Config", this); m_recycleScenesInWidgetConfigAction->setCheckable(true); - m_softwareRenderingWidgetsAction = new QAction("Software Rendering in Widgets", this); - m_softwareRenderingWidgetsAction->setCheckable(true); - connect(m_softwareRenderingWidgetsAction, SIGNAL(toggled(bool)), SLOT(slotSoftwareRenderingWidgets(bool))); - - m_configNumWidgets1Action = new QAction("1 Widget", this); - m_configNumWidgets2Action = new QAction("2 Widgets", this); - m_configNumWidgets4Action = new QAction("4 Widgets", this); - m_configNumWidgetsNoneAction= new QAction("No Widgets", this); - connect(m_configNumWidgets1Action, SIGNAL(triggered()), SLOT(slotConfigNumWidgets())); - connect(m_configNumWidgets2Action, SIGNAL(triggered()), SLOT(slotConfigNumWidgets())); - connect(m_configNumWidgets4Action, SIGNAL(triggered()), SLOT(slotConfigNumWidgets())); - connect(m_configNumWidgetsNoneAction, SIGNAL(triggered()), SLOT(slotConfigNumWidgets())); - - m_createSphereAndBoxSceneAction = new QAction("Sphere And Box Scene", this); - m_createSpheresSceneAction = new QAction("Spheres Scene", this); - m_createBoxesSceneAction = new QAction("Boxes Scene", this); - m_createTrianglesSceneAction = new QAction("Triangles Scene", this); - m_allWidgetsDifferentSceneAction = new QAction("All Widgets Show Different Scene", this); - m_clearSceneAction = new QAction("Clear Scene", this); - connect(m_createSphereAndBoxSceneAction, SIGNAL(triggered()), SLOT(slotCreateSphereAndBoxScene())); - connect(m_createSpheresSceneAction, SIGNAL(triggered()), SLOT(slotCreateSpheresScene())); - connect(m_createBoxesSceneAction, SIGNAL(triggered()), SLOT(slotCreateBoxesScene())); - connect(m_createTrianglesSceneAction, SIGNAL(triggered()), SLOT(slotCreateTrianglesScene())); - connect(m_allWidgetsDifferentSceneAction, SIGNAL(triggered()), SLOT(slotAllWidgetsDifferentScene())); - connect(m_clearSceneAction, SIGNAL(triggered()), SLOT(slotClearScene())); - - m_useBufferObjectsAction = new QAction("Use Buffer Objects", this); - m_useClientVertexArraysAction = new QAction("Use Client Vertex Arrays", this); - connect(m_useBufferObjectsAction, SIGNAL(triggered()), SLOT(slotUseBufferObjects())); - connect(m_useClientVertexArraysAction, SIGNAL(triggered()), SLOT(slotUseClientVertexArrays())); - - m_deleteAllResourcesInResourceManagerAction = new QAction("Delete All Resources In Resource Manager", this); - connect(m_deleteAllResourcesInResourceManagerAction, SIGNAL(triggered()), SLOT(slotDeleteAllResourcesInResourceManager())); - + m_configNumWidgets1Action = new QAction("1 Widget", this); + m_configNumWidgets2Action = new QAction("2 Widgets", this); + m_configNumWidgets4Action = new QAction("4 Widgets", this); + m_configNumWidgetsNoneAction = new QAction("No Widgets", this); + connect(m_configNumWidgets1Action, SIGNAL(triggered()), SLOT(slotConfigNumVizWidgets())); + connect(m_configNumWidgets2Action, SIGNAL(triggered()), SLOT(slotConfigNumVizWidgets())); + connect(m_configNumWidgets4Action, SIGNAL(triggered()), SLOT(slotConfigNumVizWidgets())); + connect(m_configNumWidgetsNoneAction, SIGNAL(triggered()), SLOT(slotConfigNumVizWidgets())); - QMenu* widgetsMenu = menuBar()->addMenu("&Widgets"); - widgetsMenu->addAction(m_recycleScenesInWidgetConfigAction); + widgetsMenu->addAction(m_createWidgetsAsFloatingDialogsAction); widgetsMenu->addSeparator(); - widgetsMenu->addAction(m_softwareRenderingWidgetsAction); + widgetsMenu->addAction(m_recycleScenesInWidgetConfigAction); widgetsMenu->addSeparator(); widgetsMenu->addAction(m_configNumWidgets1Action); widgetsMenu->addAction(m_configNumWidgets2Action); widgetsMenu->addAction(m_configNumWidgets4Action); widgetsMenu->addAction(m_configNumWidgetsNoneAction); + widgetsMenu->addSeparator(); + widgetsMenu->addAction("Delete First Widget", this, SLOT(slotDeleteFirstVizWidget())); + widgetsMenu->addAction("Delete Second Widget", this, SLOT(slotDeleteSecondVizWidget())); + QMenu* scenesMenu = menuBar()->addMenu("&Scenes"); - scenesMenu->addAction(m_createSphereAndBoxSceneAction); - scenesMenu->addAction(m_createSpheresSceneAction); - scenesMenu->addAction(m_createBoxesSceneAction); - scenesMenu->addAction(m_createTrianglesSceneAction); + + m_useShadersAction = new QAction("Use Shaders When Creating Scenes", this); + m_useShadersAction->setCheckable(true); + m_useShadersAction->setChecked(true); + + scenesMenu->addAction(m_useShadersAction); scenesMenu->addSeparator(); - scenesMenu->addAction(m_allWidgetsDifferentSceneAction); + scenesMenu->addAction("Sphere And Box Scene", this, SLOT(slotCreateSphereAndBoxScene())); + scenesMenu->addAction("Spheres Scene", this, SLOT(slotCreateSpheresScene())); + scenesMenu->addAction("Boxes Scene", this, SLOT(slotCreateBoxesScene())); + scenesMenu->addAction("Triangles Scene", this, SLOT(slotCreateTrianglesScene())); scenesMenu->addSeparator(); - scenesMenu->addAction(m_clearSceneAction); + scenesMenu->addAction("All Widgets Show Different Scene", this, SLOT(slotAllWidgetsDifferentScene())); + scenesMenu->addSeparator(); + scenesMenu->addAction("Clear Scene", this, SLOT(slotClearScene())); + QMenu* renderingMenu = menuBar()->addMenu("&Rendering"); - renderingMenu->addAction(m_useBufferObjectsAction); - renderingMenu->addAction(m_useClientVertexArraysAction); + renderingMenu->addAction("Use Buffer Objects", this, SLOT(slotUseBufferObjects())); + renderingMenu->addAction("Use Client Vertex Arrays", this, SLOT(slotUseClientVertexArrays())); + QMenu* testMenu = menuBar()->addMenu("&Test"); - testMenu->addAction(m_deleteAllResourcesInResourceManagerAction); + testMenu->addAction("Delete All Resources In Resource Manager", this, SLOT(slotDeleteAllResourcesInResourceManager())); + testMenu->addAction("Delete or Release OpenGL Resources in All Widgets", this, SLOT(slotDeleteOrReleaseOpenGLResourcesInAllVizWidgets())); + // Must create context group before launching any widgets m_contextGroup = new cvf::OpenGLContextGroup; - createVizWidgets(1, m_softwareRenderingWidgetsAction->isChecked(), false); - slotCreateSphereAndBoxScene(); + createVizWidgets(1, false); QTimer* timer = new QTimer; connect(timer, SIGNAL(timeout()), SLOT(slotUpdateStatusbar())); timer->start(250); - - /* - { - QWidget* myWidget = new QWidget; - QGridLayout* layout = new QGridLayout(myWidget); - - QLabel* l1 = new QLabel("JALLA", myWidget); - QLabel* l2 = new QLabel("BALLA", myWidget); - QLabel* l3 = new QLabel("TRALLA", myWidget); - layout->addWidget(l1, 0, 0); - layout->addWidget(l2, 0, 1); - layout->addWidget(l3, 1, 1); - - QStatusBar* sb = statusBar(); - //sb->addPermanentWidget(new QLabel("JALLA")); - sb->addPermanentWidget(myWidget); - } - */ } @@ -197,7 +168,7 @@ int QMVMainWindow::vizWidgetCount() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void QMVMainWindow::createVizWidgets(int numWidgets, bool software, bool recycleScenes) +void QMVMainWindow::createVizWidgets(int numWidgets, bool recycleScenes) { CVF_ASSERT(numWidgets <= MAX_NUM_WIDGETS); @@ -209,40 +180,39 @@ void QMVMainWindow::createVizWidgets(int numWidgets, bool software, bool recycle deleteAllVizWidgets(); - QWidget* parentWidget = centralWidget(); - QGridLayout* layout = dynamic_cast(parentWidget->layout()); - CVF_ASSERT(layout); + // Note that creating the widgets as floating dialogs will only work if the + // Qt::AA_ShareOpenGLContexts has been set using QApplication::setAttribute(Qt::AA_ShareOpenGLContexts) before Application object is constructed + const bool createAsDialogs = m_createWidgetsAsFloatingDialogsAction->isChecked(); - QGLFormat oglFormat; - if (software) - { - oglFormat.setOption(QGL::IndirectRendering); - } + QWidget* parentWidget = centralWidget(); // The context group that all the contexts end up in CVF_ASSERT(m_contextGroup.notNull()); CVF_ASSERT(m_contextGroup->contextCount() == 0); - QMVWidget* shareWidget = NULL; - int i; for (i = 0; i < numWidgets; i++) { QMVWidget* newWidget = NULL; - if (shareWidget) + + if (createAsDialogs) { - newWidget = new QMVWidget(shareWidget, parentWidget); + newWidget = new QMVWidget(m_contextGroup.p(), i, parentWidget, Qt::Dialog); + newWidget->resize(600, 400); + newWidget->show(); } else { - newWidget = new QMVWidget(m_contextGroup.p(), oglFormat, parentWidget); - shareWidget = newWidget; + newWidget = new QMVWidget(m_contextGroup.p(), i, parentWidget); + QGridLayout* layout = parentWidget ? dynamic_cast(parentWidget->layout()) : NULL; + if (layout) + { + int row = i/2; + int col = i-2*row; + layout->addWidget(newWidget, row, col); + } } - int row = i/2; - int col = i-2*row; - layout->addWidget(newWidget, row, col); - m_vizWidgets[i] = newWidget; } @@ -256,12 +226,12 @@ void QMVMainWindow::createVizWidgets(int numWidgets, bool software, bool recycle //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void QMVMainWindow::deleteAllOpenGLResourcesInAllVizWidgets() +void QMVMainWindow::deleteOrReleaseOpenGLResourcesInAllVizWidgets() { - cvf::OpenGLResourceManager* resourceManager = m_contextGroup.notNull() ? m_contextGroup->resourceManager() : NULL; + // Will be set to one of the OpenGL contexts so we can use it in final evict call + cvf::OpenGLContext* someOglContext = NULL; - // The loop below should not be needed now that we can clean up resources - // by calling on the resource manager, but leave it as long as deleteOrReleaseOpenGLResources() is in place + // Loops over all the widgets and deletes/releases the OpenGL resources for each of them int i; for (i = 0; i < MAX_NUM_WIDGETS; i++) { @@ -272,19 +242,42 @@ void QMVMainWindow::deleteAllOpenGLResourcesInAllVizWidgets() cvf::OpenGLContext* oglContext = vizWidget->cvfOpenGLContext(); CVF_ASSERT(oglContext); CVF_ASSERT(oglContext->isCurrent()); + someOglContext = oglContext; cvf::RenderSequence* renderSeq = vizWidget->renderSequence(); if (renderSeq) { renderSeq->deleteOrReleaseOpenGLResources(oglContext); } - - CVF_ASSERT(resourceManager); - resourceManager->deleteAllOpenGLResources(oglContext); } } + + cvf::OpenGLResourceManager* resourceManager = m_contextGroup.notNull() ? m_contextGroup->resourceManager() : NULL; + if (resourceManager && someOglContext) + { + resourceManager->evictOrphanedOpenGLResources(someOglContext); + } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow::deleteAllOpenGLResourcesInResourceManager() +{ + if (m_contextGroup.notNull()) + { + cvf::OpenGLResourceManager* rcMgr = m_contextGroup->resourceManager(); + CVF_ASSERT(rcMgr); + + if (m_contextGroup->contextCount() > 0) + { + // Grab any context in the group + cvf::OpenGLContext* oglContext = m_contextGroup->context(0); + oglContext->makeCurrent(); + rcMgr->deleteAllOpenGLResources(oglContext); + } + } +} //-------------------------------------------------------------------------------------------------- /// @@ -294,7 +287,9 @@ void QMVMainWindow::deleteAllVizWidgets() QWidget* parentWidget = centralWidget(); QLayout* layout = parentWidget->layout(); - deleteAllOpenGLResourcesInAllVizWidgets(); + // Should not be needed, but left for experimentation + //deleteOrReleaseOpenGLResourcesInAllVizWidgets(); + //deleteAllOpenGLResourcesInResourceManager(); int i; for (i = 0; i < MAX_NUM_WIDGETS; i++) @@ -310,6 +305,21 @@ void QMVMainWindow::deleteAllVizWidgets() CVF_ASSERT(m_contextGroup.isNull() || m_contextGroup->contextCount() == 0); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow::deleteVizWidgetAt(int index) +{ + QWidget* parentWidget = centralWidget(); + QLayout* layout = parentWidget->layout(); + + if (m_vizWidgets[index]) + { + layout->removeWidget(m_vizWidgets[index]); + delete m_vizWidgets[index]; + m_vizWidgets[index] = NULL; + } +} //-------------------------------------------------------------------------------------------------- /// @@ -323,7 +333,7 @@ void QMVMainWindow::setSceneInAllVizWidgets(cvf::Scene* scene) { if (m_vizWidgets[i] != NULL) { - ref renderSeq = factory.createFromScene(scene); + cvf::ref renderSeq = factory.createFromScene(scene); m_vizWidgets[i]->setRenderSequence(renderSeq.p()); } } @@ -348,7 +358,7 @@ void QMVMainWindow::spreadScenesAcrossVizWidgets(cvf::Collection* sc cvf::Scene* scene = (sceneCollection->size() > i) ? sceneCollection->at(i) : NULL; if (scene) { - ref renderSeq = factory.createFromScene(scene); + cvf::ref renderSeq = factory.createFromScene(scene); vizWidget->setRenderSequence(renderSeq.p()); } } @@ -439,49 +449,56 @@ void QMVMainWindow::setRenderModeInAllModels(cvf::DrawableGeo::RenderMode render //-------------------------------------------------------------------------------------------------- void QMVMainWindow::closeEvent(QCloseEvent*) { - deleteAllOpenGLResourcesInAllVizWidgets(); + // Should not be needed any more, but left for experimentation + //deleteOrReleaseOpenGLResourcesInAllVizWidgets(); + //deleteAllOpenGLResourcesInResourceManager(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void QMVMainWindow::slotSoftwareRenderingWidgets(bool software) +void QMVMainWindow::slotConfigNumVizWidgets() { - int currNumWidgets = vizWidgetCount(); + QObject* senderAct = sender(); - // Just recreate with the same number of widgets - createVizWidgets(currNumWidgets, software, m_recycleScenesInWidgetConfigAction->isChecked()); -} + bool recycleScenes = m_recycleScenesInWidgetConfigAction->isChecked(); + if (senderAct == m_configNumWidgets1Action) createVizWidgets(1, recycleScenes); + else if (senderAct == m_configNumWidgets2Action) createVizWidgets(2, recycleScenes); + else if (senderAct == m_configNumWidgets4Action) createVizWidgets(4, recycleScenes); + else if (senderAct == m_configNumWidgetsNoneAction) createVizWidgets(0, recycleScenes); +} //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void QMVMainWindow::slotConfigNumWidgets() +void QMVMainWindow::slotDeleteFirstVizWidget() { - QObject* senderAct = sender(); - - bool software = m_softwareRenderingWidgetsAction->isChecked(); - bool recycleScenes = m_recycleScenesInWidgetConfigAction->isChecked(); - - if (senderAct == m_configNumWidgets1Action) createVizWidgets(1, software, recycleScenes); - else if (senderAct == m_configNumWidgets2Action) createVizWidgets(2, software, recycleScenes); - else if (senderAct == m_configNumWidgets4Action) createVizWidgets(4, software, recycleScenes); - else if (senderAct == m_configNumWidgetsNoneAction) createVizWidgets(0, software, recycleScenes); + deleteVizWidgetAt(0); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow::slotDeleteSecondVizWidget() +{ + deleteVizWidgetAt(1); +} //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void QMVMainWindow::slotCreateSphereAndBoxScene() { - QMVModelFactory modelFactory(!m_softwareRenderingWidgetsAction->isChecked()); + // Without initialization we're not getting the correct capabilities + CVF_ASSERT(m_contextGroup->isContextGroupInitialized()); + + QMVModelFactory modelFactory(m_useShadersAction->isChecked(), *m_contextGroup->capabilities()); QMVSceneFactory sceneFactory(&modelFactory); - ref model = modelFactory.createSphereAndBox(); - ref scene = sceneFactory.createFromModel(model.p()); + cvf::ref model = modelFactory.createSphereAndBox(); + cvf::ref scene = sceneFactory.createFromModel(model.p()); setSceneInAllVizWidgets(scene.p()); } @@ -492,11 +509,14 @@ void QMVMainWindow::slotCreateSphereAndBoxScene() //-------------------------------------------------------------------------------------------------- void QMVMainWindow::slotCreateSpheresScene() { - QMVModelFactory modelFactory(!m_softwareRenderingWidgetsAction->isChecked()); + // Without initialization we're not getting the correct capabilities + CVF_ASSERT(m_contextGroup->isContextGroupInitialized()); + + QMVModelFactory modelFactory(m_useShadersAction->isChecked(), *m_contextGroup->capabilities()); QMVSceneFactory sceneFactory(&modelFactory); - ref model = modelFactory.createSpheres(); - ref scene = sceneFactory.createFromModel(model.p()); + cvf::ref model = modelFactory.createSpheres(); + cvf::ref scene = sceneFactory.createFromModel(model.p()); setSceneInAllVizWidgets(scene.p()); } @@ -507,11 +527,14 @@ void QMVMainWindow::slotCreateSpheresScene() //-------------------------------------------------------------------------------------------------- void QMVMainWindow::slotCreateBoxesScene() { - QMVModelFactory modelFactory(!m_softwareRenderingWidgetsAction->isChecked()); + // Without initialization we're not getting the correct capabilities + CVF_ASSERT(m_contextGroup->isContextGroupInitialized()); + + QMVModelFactory modelFactory(m_useShadersAction->isChecked(), *m_contextGroup->capabilities()); QMVSceneFactory sceneFactory(&modelFactory); - ref model = modelFactory.createBoxes(); - ref scene = sceneFactory.createFromModel(model.p()); + cvf::ref model = modelFactory.createBoxes(); + cvf::ref scene = sceneFactory.createFromModel(model.p()); setSceneInAllVizWidgets(scene.p()); } @@ -522,11 +545,14 @@ void QMVMainWindow::slotCreateBoxesScene() //-------------------------------------------------------------------------------------------------- void QMVMainWindow::slotCreateTrianglesScene() { - QMVModelFactory modelFactory(!m_softwareRenderingWidgetsAction->isChecked()); + // Without initialization we're not getting the correct capabilities + CVF_ASSERT(m_contextGroup->isContextGroupInitialized()); + + QMVModelFactory modelFactory(m_useShadersAction->isChecked(), *m_contextGroup->capabilities()); QMVSceneFactory sceneFactory(&modelFactory); - ref model = modelFactory.createTriangles(); - ref scene = sceneFactory.createFromModel(model.p()); + cvf::ref model = modelFactory.createTriangles(); + cvf::ref scene = sceneFactory.createFromModel(model.p()); setSceneInAllVizWidgets(scene.p()); } @@ -537,7 +563,10 @@ void QMVMainWindow::slotCreateTrianglesScene() //-------------------------------------------------------------------------------------------------- void QMVMainWindow::slotAllWidgetsDifferentScene() { - QMVModelFactory modelFactory(!m_softwareRenderingWidgetsAction->isChecked()); + // Without initialization we're not getting the correct capabilities + CVF_ASSERT(m_contextGroup->isContextGroupInitialized()); + + QMVModelFactory modelFactory(m_useShadersAction->isChecked(), *m_contextGroup->capabilities()); QMVSceneFactory sceneFactory(&modelFactory); QMVRenderSequenceFactory renderSeqFactory; @@ -546,8 +575,8 @@ void QMVMainWindow::slotAllWidgetsDifferentScene() { if (m_vizWidgets[i] != NULL) { - ref scene = sceneFactory.createNumberedScene(i); - ref renderSeq = renderSeqFactory.createFromScene(scene.p()); + cvf::ref scene = sceneFactory.createNumberedScene(i); + cvf::ref renderSeq = renderSeqFactory.createFromScene(scene.p()); m_vizWidgets[i]->setRenderSequence(renderSeq.p()); } } @@ -597,23 +626,16 @@ void QMVMainWindow::slotUseClientVertexArrays() //-------------------------------------------------------------------------------------------------- void QMVMainWindow::slotDeleteAllResourcesInResourceManager() { - if (m_contextGroup.notNull()) - { - cvf::OpenGLResourceManager* rcMgr = m_contextGroup->resourceManager(); - CVF_ASSERT(rcMgr); - - QMVWidget* vizWidget = m_vizWidgets[0]; - cvf::OpenGLContext* oglContext = vizWidget ? vizWidget->cvfOpenGLContext() : NULL; - if (oglContext) - { - oglContext->makeCurrent(); - rcMgr->deleteAllOpenGLResources(oglContext); - } - } - - redrawAllVizWidgets(); + deleteAllOpenGLResourcesInResourceManager(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow::slotDeleteOrReleaseOpenGLResourcesInAllVizWidgets() +{ + deleteOrReleaseOpenGLResourcesInAllVizWidgets(); +} //-------------------------------------------------------------------------------------------------- /// @@ -640,14 +662,20 @@ void QMVMainWindow::slotUpdateStatusbar() if (renderSeq) { cvf::PerformanceInfo pi = renderSeq->performanceInfo(); - QGLFormat oglFormat = vizWidget->format(); - QString hwSw = oglFormat.testOption(QGL::IndirectRendering) ? "sw" : "hw"; - QString viewMsg = QString("V%1(%2) #p=%3 #t=%4 ").arg(i).arg(hwSw).arg(pi.visiblePartsCount).arg((pi.triangleCount)); + QString viewMsg = QString("V%1 #p=%2 #t=%3 ").arg(i).arg(pi.visiblePartsCount).arg((pi.triangleCount)); msg += viewMsg; } } } + if (m_contextGroup.notNull()) + { + const cvf::OpenGLInfo info = m_contextGroup->info(); + msg += QString(" | ") + QString::fromStdString(info.renderer().toStdString()); + } + QStatusBar* sb = statusBar(); sb->showMessage(msg); } + + diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMainWindow.h b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMainWindow.h index 50eaf7e8fd..f1628b59a0 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMainWindow.h +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVMainWindow.h @@ -34,20 +34,18 @@ // //################################################################################################## - #pragma once #include "cvfBase.h" #include "cvfCollection.h" #include "cvfDrawableGeo.h" -#include #include +#include class QMVWidget; namespace cvf { - class View; class Scene; class OpenGLResourceManager; class OpenGLContextGroup; @@ -70,22 +68,24 @@ class QMVMainWindow : public QMainWindow private: int vizWidgetCount(); - void createVizWidgets(int numWidgets, bool software, bool recycleScenes); - void deleteAllOpenGLResourcesInAllVizWidgets(); + void createVizWidgets(int numWidgets, bool recycleScenes); + void deleteAllOpenGLResourcesInResourceManager(); + void deleteOrReleaseOpenGLResourcesInAllVizWidgets(); void deleteAllVizWidgets(); + void deleteVizWidgetAt(int index); void setSceneInAllVizWidgets(cvf::Scene* scene); void spreadScenesAcrossVizWidgets(cvf::Collection* sceneCollection); void gatherAllScenes(cvf::Collection* sceneCollection); void redrawAllVizWidgets(); void setRenderModeInAllModels(cvf::DrawableGeo::RenderMode renderMode); - // Protected overrides protected: virtual void closeEvent(QCloseEvent* pCE); private slots: - void slotSoftwareRenderingWidgets(bool); - void slotConfigNumWidgets(); + void slotConfigNumVizWidgets(); + void slotDeleteFirstVizWidget(); + void slotDeleteSecondVizWidget(); void slotCreateSphereAndBoxScene(); void slotCreateSpheresScene(); @@ -98,31 +98,22 @@ private slots: void slotUseClientVertexArrays(); void slotDeleteAllResourcesInResourceManager(); + void slotDeleteOrReleaseOpenGLResourcesInAllVizWidgets(); void slotUpdateStatusbar(); private: static const int MAX_NUM_WIDGETS = 4; cvf::ref m_contextGroup; - QMVWidget* m_vizWidgets[MAX_NUM_WIDGETS]; + QPointer m_vizWidgets[MAX_NUM_WIDGETS]; + QAction* m_createWidgetsAsFloatingDialogsAction; QAction* m_recycleScenesInWidgetConfigAction; - QAction* m_softwareRenderingWidgetsAction; QAction* m_configNumWidgets1Action; QAction* m_configNumWidgets2Action; QAction* m_configNumWidgets4Action; QAction* m_configNumWidgetsNoneAction; - QAction* m_createSphereAndBoxSceneAction; - QAction* m_createSpheresSceneAction; - QAction* m_createBoxesSceneAction; - QAction* m_createTrianglesSceneAction; - QAction* m_allWidgetsDifferentSceneAction; - QAction* m_clearSceneAction; - - QAction* m_useBufferObjectsAction; - QAction* m_useClientVertexArraysAction; - - QAction* m_deleteAllResourcesInResourceManagerAction; + QAction* m_useShadersAction; }; diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVWidget.cpp b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVWidget.cpp index 586d64f352..fb8e6ba51c 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVWidget.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVWidget.cpp @@ -34,7 +34,6 @@ // //################################################################################################## - #include "cvfLibCore.h" #include "cvfLibRender.h" #include "cvfLibGeometry.h" @@ -42,43 +41,23 @@ #include "QMVWidget.h" -#include "cvfqtOpenGLContext.h" - #include +#include -using cvf::ref; - - - -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QMVWidget::QMVWidget(cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent) -: cvfqt::OpenGLWidget(contextGroup, format, parent) -{ - m_trackball = new cvf::ManipulatorTrackball; -} //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -QMVWidget::QMVWidget(QMVWidget* shareWidget, QWidget* parent) -: cvfqt::OpenGLWidget(shareWidget, parent) +QMVWidget::QMVWidget(cvf::OpenGLContextGroup* contextGroup, int indexOfWidget, QWidget* parent, Qt::WindowFlags f) +: cvfqt::OpenGLWidget(contextGroup, parent, f), + m_indexOfWidget(indexOfWidget), + m_paintCount(0) { m_trackball = new cvf::ManipulatorTrackball; } -//-------------------------------------------------------------------------------------------------- -/// -//-------------------------------------------------------------------------------------------------- -QMVWidget::~QMVWidget() -{ - cvfShutdownOpenGLContext(); -} - - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -114,6 +93,14 @@ cvf::RenderSequence* QMVWidget::renderSequence() } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::OpenGLContext* QMVWidget::cvfOpenGLContext() +{ + return cvfqt::OpenGLWidget::cvfOpenGLContext(); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -125,10 +112,6 @@ void QMVWidget::resizeGL(int width, int height) camera->viewport()->set(0, 0, width, height); camera->setProjectionAsPerspective(camera->fieldOfViewYDeg(), camera->nearPlane(), camera->farPlane()); } - else - { - glViewport(0, 0, width, height); - } } @@ -141,7 +124,7 @@ void QMVWidget::paintGL() CVF_ASSERT(currentOglContext); CVF_CHECK_OGL(currentOglContext); - cvfqt::OpenGLContext::saveOpenGLState(currentOglContext); + cvf::OpenGLUtils::pushOpenGLState(currentOglContext); if (m_renderSequence.notNull()) { @@ -149,11 +132,17 @@ void QMVWidget::paintGL() } else { - glClearColor(0.5f, 0.5f, 0.5f, 1.0f); + // Reddish background for empty widgets + glClearColor(0.9f, 0.5f, 0.5f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); } - cvfqt::OpenGLContext::restoreOpenGLState(currentOglContext); + cvf::OpenGLUtils::popOpenGLState(currentOglContext); + + m_paintCount++; + QPainter p(this); + p.setPen(Qt::red); + p.drawText(10, 20, QString("VP%1, paint count: %2").arg(m_indexOfWidget).arg(m_paintCount)); } @@ -183,8 +172,13 @@ void QMVWidget::mouseMoveEvent(QMouseEvent* event) if (m_renderSequence.isNull()) return; Qt::MouseButtons mouseBn = event->buttons(); - int posX = event->x(); - int posY = height() - event->y(); +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + const int posX = event->position().toPoint().x(); + const int posY = height() - event->position().toPoint().y(); +#else + const int posX = event->x(); + const int posY = height() - event->y(); +#endif cvf::ManipulatorTrackball::NavigationType navType = cvf::ManipulatorTrackball::NONE; if (mouseBn == Qt::LeftButton) @@ -195,7 +189,7 @@ void QMVWidget::mouseMoveEvent(QMouseEvent* event) { navType = cvf::ManipulatorTrackball::ROTATE; } - else if (mouseBn == (Qt::LeftButton | Qt::RightButton) || mouseBn == Qt::MidButton) + else if (mouseBn == (Qt::LeftButton | Qt::RightButton) || mouseBn == Qt::MiddleButton) { navType = cvf::ManipulatorTrackball::WALK; } @@ -220,10 +214,18 @@ void QMVWidget::mousePressEvent(QMouseEvent* event) { if (m_renderSequence.isNull()) return; +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + const int posX = event->position().toPoint().x(); + const int posY = height() - event->position().toPoint().y(); +#else + const int posX = event->x(); + const int posY = height() - event->y(); +#endif + if (event->buttons() == Qt::LeftButton && event->modifiers() == Qt::ControlModifier) { cvf::Rendering* r = m_renderSequence->firstRendering(); - ref ris = r->rayIntersectSpecFromWindowCoordinates(event->x(), height() - event->y()); + cvf::ref ris = r->rayIntersectSpecFromWindowCoordinates(posX, posY); cvf::HitItemCollection hic; if (r->rayIntersect(*ris, &hic)) @@ -247,3 +249,5 @@ void QMVWidget::mouseReleaseEvent(QMouseEvent* /*event*/) { m_trackball->endNavigation(); } + + diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVWidget.h b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVWidget.h index f9d1d0812c..b983d9e138 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVWidget.h +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView/QMVWidget.h @@ -34,12 +34,12 @@ // //################################################################################################## - #pragma once #include "cvfBase.h" #include "cvfRenderSequence.h" #include "cvfManipulatorTrackball.h" + #include "cvfqtOpenGLWidget.h" @@ -53,13 +53,13 @@ class QMVWidget : public cvfqt::OpenGLWidget Q_OBJECT public: - QMVWidget(cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent); - QMVWidget(QMVWidget* shareWidget, QWidget* parent); - ~QMVWidget(); + QMVWidget(cvf::OpenGLContextGroup* contextGroup, int indexOfWidget, QWidget* parent, Qt::WindowFlags f = Qt::WindowFlags()); void setRenderSequence(cvf::RenderSequence* renderSequence); cvf::RenderSequence* renderSequence(); + cvf::OpenGLContext* cvfOpenGLContext(); + private: void resizeGL(int width, int height); void paintGL(); @@ -70,8 +70,10 @@ class QMVWidget : public cvfqt::OpenGLWidget void mouseReleaseEvent(QMouseEvent* event); private: - cvf::ref m_renderSequence; + int m_indexOfWidget; + int m_paintCount; cvf::ref m_trackball; + cvf::ref m_renderSequence; }; diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/CMakeLists.txt new file mode 100644 index 0000000000..0f9c5d279e --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/CMakeLists.txt @@ -0,0 +1,51 @@ +project(QtMultiView_deprecated) + + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_BASE_CXX_FLAGS}") + +if (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long") +endif() + + +find_package(OpenGL) + +include_directories(${LibCore_SOURCE_DIR}) +include_directories(${LibGeometry_SOURCE_DIR}) +include_directories(${LibRender_SOURCE_DIR}) +include_directories(${LibViewing_SOURCE_DIR}) +include_directories(${LibGuiQt_SOURCE_DIR}) +include_directories(${LibUtilities_SOURCE_DIR}) + +set(CEE_LIBS LibUtilities LibGuiQt LibViewing LibRender LibGeometry LibIo LibCore) +set(EXTERNAL_LIBS) + +set(CEE_SOURCE_FILES +QMVFactory_deprecated.cpp +QMVMain_deprecated.cpp +QMVMainWindow_deprecated.cpp +QMVWidget_deprecated.cpp +) + +# Headers that need MOCing +set(MOC_HEADER_FILES +QMVMainWindow_deprecated.h +QMVWidget_deprecated.h +) + +# Qt +if (CEE_USE_QT5) + find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) + set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) +else() + message(FATAL_ERROR "No supported Qt version selected for build") +endif() + +set(SYSTEM_LIBRARIES) +if (CMAKE_COMPILER_IS_GNUCXX) + set(SYSTEM_LIBRARIES -lrt -lpthread) +endif(CMAKE_COMPILER_IS_GNUCXX) + +add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) +target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${SYSTEM_LIBRARIES}) diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVFactory_deprecated.cpp b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVFactory_deprecated.cpp new file mode 100644 index 0000000000..1c43343ca2 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVFactory_deprecated.cpp @@ -0,0 +1,341 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#include "cvfLibCore.h" +#include "cvfLibRender.h" +#include "cvfLibGeometry.h" +#include "cvfLibViewing.h" + +#include "cvfuPartCompoundGenerator.h" + +#include "QMVFactory_deprecated.h" + + + + +//================================================================================================== +// +// +// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMVModelFactory_deprecated::QMVModelFactory_deprecated(bool useShaders) +: m_useShaders(useShaders) +{ +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +ref QMVModelFactory_deprecated::createSphereAndBox() +{ + ref model = new cvf::ModelBasicList; + + { + cvf::GeometryBuilderDrawableGeo builder; + cvf::GeometryUtils::createSphere(2, 10, 10, &builder); + + ref eff = new cvf::Effect; + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::BLUE)); + if (m_useShaders) + { + ref prog = createProgramStandardHeadlightColor(); + eff->setShaderProgram(prog.p()); + eff->setUniform(new cvf::UniformFloat("u_color", cvf::Color4f(cvf::Color3::GREEN))); + } + + ref part = new cvf::Part; + part->setName("MySphere"); + part->setDrawable(0, builder.drawableGeo().p()); + part->setEffect(eff.p()); + + model->addPart(part.p()); + } + + { + cvf::GeometryBuilderDrawableGeo builder; + cvf::GeometryUtils::createBox(cvf::Vec3f(5, 0, 0), 2, 3, 4, &builder); + + ref eff = new cvf::Effect; + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::RED)); + if (m_useShaders) + { + ref prog = createProgramUnlit(); + eff->setShaderProgram(prog.p()); + eff->setUniform(new cvf::UniformFloat("u_color", cvf::Color4f(cvf::Color3::GREEN))); + } + + ref part = new cvf::Part; + part->setName("MyBox"); + part->setDrawable(0, builder.drawableGeo().p()); + part->setEffect(eff.p()); + + model->addPart(part.p()); + } + + model->updateBoundingBoxesRecursive(); + + return model; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +ref QMVModelFactory_deprecated::createSpheres() +{ + cvfu::PartCompoundGenerator gen; + gen.setPartDistribution(cvf::Vec3i(5, 5, 5)); + gen.setNumEffects(8); + gen.useRandomEffectAssignment(false); + gen.setExtent(cvf::Vec3f(3,3,3)); + gen.setOrigin(cvf::Vec3f(-1.5f, -1.5f, -1.5f)); + + cvf::Collection parts; + gen.generateSpheres(20, 20, &parts); + + ref model = new cvf::ModelBasicList; + + ref prog = createProgramStandardHeadlightColor(); + + size_t i; + for (i = 0; i < parts.size(); i++) + { + cvf::Part* part = parts[i].p(); + if (m_useShaders) + { + cvf::Effect* eff = part->effect(); + eff->setShaderProgram(prog.p()); + eff->setUniform(new cvf::UniformFloat("u_color", cvf::Color4f(cvf::Color3::INDIGO))); + } + model->addPart(part); + } + + model->updateBoundingBoxesRecursive(); + + return model; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +ref QMVModelFactory_deprecated::createBoxes() +{ + cvfu::PartCompoundGenerator gen; + gen.setPartDistribution(cvf::Vec3i(5, 5, 5)); + gen.setNumEffects(8); + gen.useRandomEffectAssignment(false); + gen.setExtent(cvf::Vec3f(3,3,3)); + gen.setOrigin(cvf::Vec3f(-1.5f, -1.5f, -1.5f)); + + cvf::Collection parts; + gen.generateBoxes(&parts); + + ref model = new cvf::ModelBasicList; + + ref prog = createProgramStandardHeadlightColor(); + + size_t i; + for (i = 0; i < parts.size(); i++) + { + cvf::Part* part = parts[i].p(); + if (m_useShaders) + { + cvf::Effect* eff = part->effect(); + eff->setShaderProgram(prog.p()); + eff->setUniform(new cvf::UniformFloat("u_color", cvf::Color4f(cvf::Color3::CYAN))); + } + model->addPart(part); + } + + model->updateBoundingBoxesRecursive(); + + return model; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +ref QMVModelFactory_deprecated::createTriangles() +{ + cvfu::PartCompoundGenerator gen; + gen.setPartDistribution(cvf::Vec3i(5, 5, 5)); + gen.setNumEffects(8); + gen.useRandomEffectAssignment(false); + gen.setExtent(cvf::Vec3f(3,3,3)); + gen.setOrigin(cvf::Vec3f(-1.5f, -1.5f, -1.5f)); + + cvf::Collection parts; + gen.generateTriangles(&parts); + + ref model = new cvf::ModelBasicList; + + ref prog = createProgramStandardHeadlightColor(); + + size_t i; + for (i = 0; i < parts.size(); i++) + { + cvf::Part* part = parts[i].p(); + if (m_useShaders) + { + cvf::Effect* eff = part->effect(); + eff->setShaderProgram(prog.p()); + eff->setUniform(new cvf::UniformFloat("u_color", cvf::Color4f(cvf::Color3::GOLD))); + } + model->addPart(part); + } + + model->updateBoundingBoxesRecursive(); + + return model; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +ref QMVModelFactory_deprecated::createProgramStandardHeadlightColor() +{ + cvf::ShaderProgramGenerator gen("StandardHeadlightColor", cvf::ShaderSourceProvider::instance()); + gen.configureStandardHeadlightColor(); + ref prog = gen.generate(); + return prog; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +ref QMVModelFactory_deprecated::createProgramUnlit() +{ + cvf::ShaderProgramGenerator gen("Unlit", cvf::ShaderSourceProvider::instance()); + gen.addVertexCode(cvf::ShaderSourceRepository::vs_Standard); + gen.addFragmentCode(cvf::ShaderSourceRepository::src_Color); + gen.addFragmentCode(cvf::ShaderSourceRepository::fs_Unlit); + ref prog = gen.generate(); + return prog; +} + + +//================================================================================================== +// +// +// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMVSceneFactory_deprecated::QMVSceneFactory_deprecated(QMVModelFactory_deprecated* modelFactory) +: m_modelFactory(modelFactory) +{ +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +ref QMVSceneFactory_deprecated::createNumberedScene(int sceneNumber) +{ + ref model; + switch (sceneNumber) + { + case 0: model = m_modelFactory->createSphereAndBox(); break; + case 1: model = m_modelFactory->createSpheres(); break; + case 2: model = m_modelFactory->createBoxes(); break; + default: model = m_modelFactory->createTriangles(); break; + } + + return createFromModel(model.p()); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +ref QMVSceneFactory_deprecated::createFromModel(cvf::Model* model) +{ + ref scene = new cvf::Scene; + + if (model) + { + scene->addModel(model); + } + + return scene; +} + + + +//================================================================================================== +// +// +// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +ref QMVRenderSequenceFactory_deprecated::createFromScene(cvf::Scene* scene) +{ + ref rendering = new cvf::Rendering; + rendering->renderEngine()->enableItemCountUpdate(true); + rendering->setScene(scene); + + cvf::Camera* cam = rendering->camera(); + rendering->addOverlayItem(new cvf::OverlayAxisCross(cam, new cvf::FixedAtlasFont(cvf::FixedAtlasFont::STANDARD))); + + if (scene) + { + cvf::BoundingBox bb = scene->boundingBox(); + if (bb.isValid()) + { + cam->fitView(bb, -cvf::Vec3d::Z_AXIS, cvf::Vec3d::Y_AXIS); + } + } + + ref renderSeq = new cvf::RenderSequence; + renderSeq->addRendering(rendering.p()); + + return renderSeq; +} diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVFactory_deprecated.h b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVFactory_deprecated.h new file mode 100644 index 0000000000..850e17a405 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVFactory_deprecated.h @@ -0,0 +1,97 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#pragma once + +using cvf::ref; + + +//================================================================================================== +// +// +// +//================================================================================================== +class QMVModelFactory_deprecated +{ +public: + QMVModelFactory_deprecated(bool useShaders); + + ref createSphereAndBox(); + ref createSpheres(); + ref createBoxes(); + ref createTriangles(); + +private: + ref createProgramStandardHeadlightColor(); + ref createProgramUnlit(); + +private: + bool m_useShaders; +}; + + + +//================================================================================================== +// +// +// +//================================================================================================== +class QMVSceneFactory_deprecated +{ +public: + QMVSceneFactory_deprecated(QMVModelFactory_deprecated* modelFactory); + + ref createNumberedScene(int sceneNumber); + ref createFromModel(cvf::Model* model); + +private: + QMVModelFactory_deprecated* m_modelFactory; +}; + + + +//================================================================================================== +// +// +// +//================================================================================================== +class QMVRenderSequenceFactory_deprecated +{ +public: + ref createFromScene(cvf::Scene* model); +}; + diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVMainWindow_deprecated.cpp b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVMainWindow_deprecated.cpp new file mode 100644 index 0000000000..0a5d1b3c4d --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVMainWindow_deprecated.cpp @@ -0,0 +1,653 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#include "cvfLibCore.h" +#include "cvfLibRender.h" +#include "cvfLibGeometry.h" +#include "cvfLibViewing.h" + +#include "QMVMainWindow_deprecated.h" +#include "QMVWidget_deprecated.h" +#include "QMVFactory_deprecated.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +using cvf::ref; + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMVMainWindow_deprecated::QMVMainWindow_deprecated() +{ + memset(m_vizWidgets, 0, sizeof(m_vizWidgets)); + + QFrame* mainFrame = new QFrame; + QGridLayout* frameLayout = new QGridLayout; + mainFrame->setLayout(frameLayout); + setCentralWidget(mainFrame); + + + m_recycleScenesInWidgetConfigAction = new QAction("Recycle Scenes When Changing Widget Config", this); + m_recycleScenesInWidgetConfigAction->setCheckable(true); + + m_softwareRenderingWidgetsAction = new QAction("Software Rendering in Widgets", this); + m_softwareRenderingWidgetsAction->setCheckable(true); + connect(m_softwareRenderingWidgetsAction, SIGNAL(toggled(bool)), SLOT(slotSoftwareRenderingWidgets(bool))); + + m_configNumWidgets1Action = new QAction("1 Widget", this); + m_configNumWidgets2Action = new QAction("2 Widgets", this); + m_configNumWidgets4Action = new QAction("4 Widgets", this); + m_configNumWidgetsNoneAction= new QAction("No Widgets", this); + connect(m_configNumWidgets1Action, SIGNAL(triggered()), SLOT(slotConfigNumWidgets())); + connect(m_configNumWidgets2Action, SIGNAL(triggered()), SLOT(slotConfigNumWidgets())); + connect(m_configNumWidgets4Action, SIGNAL(triggered()), SLOT(slotConfigNumWidgets())); + connect(m_configNumWidgetsNoneAction, SIGNAL(triggered()), SLOT(slotConfigNumWidgets())); + + m_createSphereAndBoxSceneAction = new QAction("Sphere And Box Scene", this); + m_createSpheresSceneAction = new QAction("Spheres Scene", this); + m_createBoxesSceneAction = new QAction("Boxes Scene", this); + m_createTrianglesSceneAction = new QAction("Triangles Scene", this); + m_allWidgetsDifferentSceneAction = new QAction("All Widgets Show Different Scene", this); + m_clearSceneAction = new QAction("Clear Scene", this); + connect(m_createSphereAndBoxSceneAction, SIGNAL(triggered()), SLOT(slotCreateSphereAndBoxScene())); + connect(m_createSpheresSceneAction, SIGNAL(triggered()), SLOT(slotCreateSpheresScene())); + connect(m_createBoxesSceneAction, SIGNAL(triggered()), SLOT(slotCreateBoxesScene())); + connect(m_createTrianglesSceneAction, SIGNAL(triggered()), SLOT(slotCreateTrianglesScene())); + connect(m_allWidgetsDifferentSceneAction, SIGNAL(triggered()), SLOT(slotAllWidgetsDifferentScene())); + connect(m_clearSceneAction, SIGNAL(triggered()), SLOT(slotClearScene())); + + m_useBufferObjectsAction = new QAction("Use Buffer Objects", this); + m_useClientVertexArraysAction = new QAction("Use Client Vertex Arrays", this); + connect(m_useBufferObjectsAction, SIGNAL(triggered()), SLOT(slotUseBufferObjects())); + connect(m_useClientVertexArraysAction, SIGNAL(triggered()), SLOT(slotUseClientVertexArrays())); + + m_deleteAllResourcesInResourceManagerAction = new QAction("Delete All Resources In Resource Manager", this); + connect(m_deleteAllResourcesInResourceManagerAction, SIGNAL(triggered()), SLOT(slotDeleteAllResourcesInResourceManager())); + + + QMenu* widgetsMenu = menuBar()->addMenu("&Widgets"); + widgetsMenu->addAction(m_recycleScenesInWidgetConfigAction); + widgetsMenu->addSeparator(); + widgetsMenu->addAction(m_softwareRenderingWidgetsAction); + widgetsMenu->addSeparator(); + widgetsMenu->addAction(m_configNumWidgets1Action); + widgetsMenu->addAction(m_configNumWidgets2Action); + widgetsMenu->addAction(m_configNumWidgets4Action); + widgetsMenu->addAction(m_configNumWidgetsNoneAction); + + QMenu* scenesMenu = menuBar()->addMenu("&Scenes"); + scenesMenu->addAction(m_createSphereAndBoxSceneAction); + scenesMenu->addAction(m_createSpheresSceneAction); + scenesMenu->addAction(m_createBoxesSceneAction); + scenesMenu->addAction(m_createTrianglesSceneAction); + scenesMenu->addSeparator(); + scenesMenu->addAction(m_allWidgetsDifferentSceneAction); + scenesMenu->addSeparator(); + scenesMenu->addAction(m_clearSceneAction); + + QMenu* renderingMenu = menuBar()->addMenu("&Rendering"); + renderingMenu->addAction(m_useBufferObjectsAction); + renderingMenu->addAction(m_useClientVertexArraysAction); + + QMenu* testMenu = menuBar()->addMenu("&Test"); + testMenu->addAction(m_deleteAllResourcesInResourceManagerAction); + + // Must create context group before launching any widgets + m_contextGroup = new cvf::OpenGLContextGroup; + + createVizWidgets(1, m_softwareRenderingWidgetsAction->isChecked(), false); + slotCreateSphereAndBoxScene(); + + QTimer* timer = new QTimer; + connect(timer, SIGNAL(timeout()), SLOT(slotUpdateStatusbar())); + timer->start(250); + + /* + { + QWidget* myWidget = new QWidget; + QGridLayout* layout = new QGridLayout(myWidget); + + QLabel* l1 = new QLabel("JALLA", myWidget); + QLabel* l2 = new QLabel("BALLA", myWidget); + QLabel* l3 = new QLabel("TRALLA", myWidget); + layout->addWidget(l1, 0, 0); + layout->addWidget(l2, 0, 1); + layout->addWidget(l3, 1, 1); + + QStatusBar* sb = statusBar(); + //sb->addPermanentWidget(new QLabel("JALLA")); + sb->addPermanentWidget(myWidget); + } + */ +} + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMVMainWindow_deprecated::~QMVMainWindow_deprecated() +{ +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int QMVMainWindow_deprecated::vizWidgetCount() +{ + int count = 0; + + int i; + for (i = 0; i < MAX_NUM_WIDGETS; i++) + { + if (m_vizWidgets[i]) + { + count++; + } + } + + return count; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::createVizWidgets(int numWidgets, bool software, bool recycleScenes) +{ + CVF_ASSERT(numWidgets <= MAX_NUM_WIDGETS); + + cvf::Collection sceneCollection; + if (recycleScenes) + { + gatherAllScenes(&sceneCollection); + } + + deleteAllVizWidgets(); + + QWidget* parentWidget = centralWidget(); + QGridLayout* layout = dynamic_cast(parentWidget->layout()); + CVF_ASSERT(layout); + + QGLFormat oglFormat; + if (software) + { + oglFormat.setOption(QGL::IndirectRendering); + } + + // The context group that all the contexts end up in + CVF_ASSERT(m_contextGroup.notNull()); + CVF_ASSERT(m_contextGroup->contextCount() == 0); + + QMVWidget_deprecated* shareWidget = NULL; + + int i; + for (i = 0; i < numWidgets; i++) + { + QMVWidget_deprecated* newWidget = NULL; + if (shareWidget) + { + newWidget = new QMVWidget_deprecated(shareWidget, parentWidget); + } + else + { + newWidget = new QMVWidget_deprecated(m_contextGroup.p(), oglFormat, parentWidget); + shareWidget = newWidget; + } + + int row = i/2; + int col = i-2*row; + layout->addWidget(newWidget, row, col); + + m_vizWidgets[i] = newWidget; + } + + if (recycleScenes) + { + spreadScenesAcrossVizWidgets(&sceneCollection); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::deleteAllOpenGLResourcesInAllVizWidgets() +{ + cvf::OpenGLResourceManager* resourceManager = m_contextGroup.notNull() ? m_contextGroup->resourceManager() : NULL; + + // The loop below should not be needed now that we can clean up resources + // by calling on the resource manager, but leave it as long as deleteOrReleaseOpenGLResources() is in place + int i; + for (i = 0; i < MAX_NUM_WIDGETS; i++) + { + QMVWidget_deprecated* vizWidget = m_vizWidgets[i]; + if (vizWidget) + { + vizWidget->makeCurrent(); + cvf::OpenGLContext* oglContext = vizWidget->cvfOpenGLContext(); + CVF_ASSERT(oglContext); + CVF_ASSERT(oglContext->isCurrent()); + + cvf::RenderSequence* renderSeq = vizWidget->renderSequence(); + if (renderSeq) + { + renderSeq->deleteOrReleaseOpenGLResources(oglContext); + } + + CVF_ASSERT(resourceManager); + resourceManager->deleteAllOpenGLResources(oglContext); + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::deleteAllVizWidgets() +{ + QWidget* parentWidget = centralWidget(); + QLayout* layout = parentWidget->layout(); + + deleteAllOpenGLResourcesInAllVizWidgets(); + + int i; + for (i = 0; i < MAX_NUM_WIDGETS; i++) + { + if (m_vizWidgets[i]) + { + layout->removeWidget(m_vizWidgets[i]); + delete m_vizWidgets[i]; + m_vizWidgets[i] = NULL; + } + } + + CVF_ASSERT(m_contextGroup.isNull() || m_contextGroup->contextCount() == 0); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::setSceneInAllVizWidgets(cvf::Scene* scene) +{ + QMVRenderSequenceFactory_deprecated factory; + + int i; + for (i = 0; i < MAX_NUM_WIDGETS; i++) + { + if (m_vizWidgets[i] != NULL) + { + ref renderSeq = factory.createFromScene(scene); + m_vizWidgets[i]->setRenderSequence(renderSeq.p()); + } + } + + redrawAllVizWidgets(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::spreadScenesAcrossVizWidgets(cvf::Collection* sceneCollection) +{ + QMVRenderSequenceFactory_deprecated factory; + + cvf::uint i; + for (i = 0; i < static_cast(MAX_NUM_WIDGETS); i++) + { + QMVWidget_deprecated* vizWidget = m_vizWidgets[i]; + if (vizWidget) + { + cvf::Scene* scene = (sceneCollection->size() > i) ? sceneCollection->at(i) : NULL; + if (scene) + { + ref renderSeq = factory.createFromScene(scene); + vizWidget->setRenderSequence(renderSeq.p()); + } + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::gatherAllScenes(cvf::Collection* sceneCollection) +{ + int i; + for (i = 0; i < MAX_NUM_WIDGETS; i++) + { + if (m_vizWidgets[i] != NULL) + { + cvf::RenderSequence* renderSeq = m_vizWidgets[i]->renderSequence(); + cvf::Rendering* rendering = renderSeq ? renderSeq->firstRendering() : NULL; + cvf::Scene* scene = rendering ? rendering->scene() : NULL; + if (scene) + { + sceneCollection->push_back(scene); + } + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::redrawAllVizWidgets() +{ + int i; + for (i = 0; i < MAX_NUM_WIDGETS; i++) + { + if (m_vizWidgets[i] != NULL) + { + m_vizWidgets[i]->update(); + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::setRenderModeInAllModels(cvf::DrawableGeo::RenderMode renderMode) +{ + int i; + for (i = 0; i < MAX_NUM_WIDGETS; i++) + { + if (m_vizWidgets[i] != NULL) + { + cvf::RenderSequence* renderSeq = m_vizWidgets[i]->renderSequence(); + cvf::Rendering* rendering = renderSeq ? renderSeq->firstRendering() : NULL; + cvf::Scene* scene = rendering ? rendering->scene() : NULL; + if (scene) + { + cvf::Collection allParts; + scene->allParts(&allParts); + + size_t numParts = allParts.size(); + size_t partIdx; + for (partIdx = 0; partIdx < numParts; partIdx++) + { + cvf::Part* part = allParts.at(partIdx); + + cvf::uint lod; + for (lod = 0; lod < cvf::Part::MAX_NUM_LOD_LEVELS; lod++) + { + cvf::DrawableGeo* drawableGeo = dynamic_cast(part->drawable(lod)); + if (drawableGeo) + { + drawableGeo->setRenderMode(renderMode); + } + } + } + } + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::closeEvent(QCloseEvent*) +{ + deleteAllOpenGLResourcesInAllVizWidgets(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotSoftwareRenderingWidgets(bool software) +{ + int currNumWidgets = vizWidgetCount(); + + // Just recreate with the same number of widgets + createVizWidgets(currNumWidgets, software, m_recycleScenesInWidgetConfigAction->isChecked()); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotConfigNumWidgets() +{ + QObject* senderAct = sender(); + + bool software = m_softwareRenderingWidgetsAction->isChecked(); + bool recycleScenes = m_recycleScenesInWidgetConfigAction->isChecked(); + + if (senderAct == m_configNumWidgets1Action) createVizWidgets(1, software, recycleScenes); + else if (senderAct == m_configNumWidgets2Action) createVizWidgets(2, software, recycleScenes); + else if (senderAct == m_configNumWidgets4Action) createVizWidgets(4, software, recycleScenes); + else if (senderAct == m_configNumWidgetsNoneAction) createVizWidgets(0, software, recycleScenes); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotCreateSphereAndBoxScene() +{ + QMVModelFactory_deprecated modelFactory(!m_softwareRenderingWidgetsAction->isChecked()); + QMVSceneFactory_deprecated sceneFactory(&modelFactory); + + ref model = modelFactory.createSphereAndBox(); + ref scene = sceneFactory.createFromModel(model.p()); + + setSceneInAllVizWidgets(scene.p()); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotCreateSpheresScene() +{ + QMVModelFactory_deprecated modelFactory(!m_softwareRenderingWidgetsAction->isChecked()); + QMVSceneFactory_deprecated sceneFactory(&modelFactory); + + ref model = modelFactory.createSpheres(); + ref scene = sceneFactory.createFromModel(model.p()); + + setSceneInAllVizWidgets(scene.p()); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotCreateBoxesScene() +{ + QMVModelFactory_deprecated modelFactory(!m_softwareRenderingWidgetsAction->isChecked()); + QMVSceneFactory_deprecated sceneFactory(&modelFactory); + + ref model = modelFactory.createBoxes(); + ref scene = sceneFactory.createFromModel(model.p()); + + setSceneInAllVizWidgets(scene.p()); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotCreateTrianglesScene() +{ + QMVModelFactory_deprecated modelFactory(!m_softwareRenderingWidgetsAction->isChecked()); + QMVSceneFactory_deprecated sceneFactory(&modelFactory); + + ref model = modelFactory.createTriangles(); + ref scene = sceneFactory.createFromModel(model.p()); + + setSceneInAllVizWidgets(scene.p()); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotAllWidgetsDifferentScene() +{ + QMVModelFactory_deprecated modelFactory(!m_softwareRenderingWidgetsAction->isChecked()); + QMVSceneFactory_deprecated sceneFactory(&modelFactory); + QMVRenderSequenceFactory_deprecated renderSeqFactory; + + int i; + for (i = 0; i < MAX_NUM_WIDGETS; i++) + { + if (m_vizWidgets[i] != NULL) + { + ref scene = sceneFactory.createNumberedScene(i); + ref renderSeq = renderSeqFactory.createFromScene(scene.p()); + m_vizWidgets[i]->setRenderSequence(renderSeq.p()); + } + } + + redrawAllVizWidgets(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotClearScene() +{ + int i; + for (i = 0; i < MAX_NUM_WIDGETS; i++) + { + if (m_vizWidgets[i] != NULL) + { + m_vizWidgets[i]->setRenderSequence(NULL); + } + } + + redrawAllVizWidgets(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotUseBufferObjects() +{ + setRenderModeInAllModels(cvf::DrawableGeo::BUFFER_OBJECT); + redrawAllVizWidgets(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotUseClientVertexArrays() +{ + setRenderModeInAllModels(cvf::DrawableGeo::VERTEX_ARRAY); + redrawAllVizWidgets(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotDeleteAllResourcesInResourceManager() +{ + if (m_contextGroup.notNull()) + { + cvf::OpenGLResourceManager* rcMgr = m_contextGroup->resourceManager(); + CVF_ASSERT(rcMgr); + + QMVWidget_deprecated* vizWidget = m_vizWidgets[0]; + cvf::OpenGLContext* oglContext = vizWidget ? vizWidget->cvfOpenGLContext() : NULL; + if (oglContext) + { + oglContext->makeCurrent(); + rcMgr->deleteAllOpenGLResources(oglContext); + } + } + + redrawAllVizWidgets(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVMainWindow_deprecated::slotUpdateStatusbar() +{ + cvf::OpenGLResourceManager* resourceManager = m_contextGroup.notNull() ? m_contextGroup->resourceManager() : NULL; + + QString msg = "N/A "; + if (resourceManager) + { + cvf::uint boCount = resourceManager->bufferObjectCount(); + double boMemUsageMB = static_cast(resourceManager->bufferObjectMemoryUsage())/(1024.0*1024.0); + msg = QString("#bo=%1 (MB=%2) | ").arg(boCount).arg(boMemUsageMB, 0, 'f', 3); + } + + int i; + for (i = 0; i < MAX_NUM_WIDGETS; i++) + { + QMVWidget_deprecated* vizWidget = m_vizWidgets[i]; + if (vizWidget) + { + cvf::RenderSequence* renderSeq = vizWidget->renderSequence(); + if (renderSeq) + { + cvf::PerformanceInfo pi = renderSeq->performanceInfo(); + QGLFormat oglFormat = vizWidget->format(); + QString hwSw = oglFormat.testOption(QGL::IndirectRendering) ? "sw" : "hw"; + QString viewMsg = QString("V%1(%2) #p=%3 #t=%4 ").arg(i).arg(hwSw).arg(pi.visiblePartsCount).arg((pi.triangleCount)); + msg += viewMsg; + } + } + } + + QStatusBar* sb = statusBar(); + sb->showMessage(msg); +} diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVMainWindow_deprecated.h b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVMainWindow_deprecated.h new file mode 100644 index 0000000000..5352d436dd --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVMainWindow_deprecated.h @@ -0,0 +1,128 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#pragma once + +#include "cvfBase.h" +#include "cvfCollection.h" +#include "cvfDrawableGeo.h" + +#include +#include + +class QMVWidget_deprecated; + +namespace cvf { + class View; + class Scene; + class OpenGLResourceManager; + class OpenGLContextGroup; +} + + + +//================================================================================================== +// +// +// +//================================================================================================== +class QMVMainWindow_deprecated : public QMainWindow +{ + Q_OBJECT + +public: + QMVMainWindow_deprecated(); + ~QMVMainWindow_deprecated(); + +private: + int vizWidgetCount(); + void createVizWidgets(int numWidgets, bool software, bool recycleScenes); + void deleteAllOpenGLResourcesInAllVizWidgets(); + void deleteAllVizWidgets(); + void setSceneInAllVizWidgets(cvf::Scene* scene); + void spreadScenesAcrossVizWidgets(cvf::Collection* sceneCollection); + void gatherAllScenes(cvf::Collection* sceneCollection); + void redrawAllVizWidgets(); + void setRenderModeInAllModels(cvf::DrawableGeo::RenderMode renderMode); + + // Protected overrides +protected: + virtual void closeEvent(QCloseEvent* pCE); + +private slots: + void slotSoftwareRenderingWidgets(bool); + void slotConfigNumWidgets(); + + void slotCreateSphereAndBoxScene(); + void slotCreateSpheresScene(); + void slotCreateBoxesScene(); + void slotCreateTrianglesScene(); + void slotAllWidgetsDifferentScene(); + void slotClearScene(); + + void slotUseBufferObjects(); + void slotUseClientVertexArrays(); + + void slotDeleteAllResourcesInResourceManager(); + + void slotUpdateStatusbar(); + +private: + static const int MAX_NUM_WIDGETS = 4; + cvf::ref m_contextGroup; + QMVWidget_deprecated* m_vizWidgets[MAX_NUM_WIDGETS]; + + QAction* m_recycleScenesInWidgetConfigAction; + QAction* m_softwareRenderingWidgetsAction; + QAction* m_configNumWidgets1Action; + QAction* m_configNumWidgets2Action; + QAction* m_configNumWidgets4Action; + QAction* m_configNumWidgetsNoneAction; + + QAction* m_createSphereAndBoxSceneAction; + QAction* m_createSpheresSceneAction; + QAction* m_createBoxesSceneAction; + QAction* m_createTrianglesSceneAction; + QAction* m_allWidgetsDifferentSceneAction; + QAction* m_clearSceneAction; + + QAction* m_useBufferObjectsAction; + QAction* m_useClientVertexArraysAction; + + QAction* m_deleteAllResourcesInResourceManagerAction; +}; + diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVMain_deprecated.cpp b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVMain_deprecated.cpp new file mode 100644 index 0000000000..6cd2167ec7 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVMain_deprecated.cpp @@ -0,0 +1,69 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#include "cvfLibCore.h" + +#include "QMVMainWindow_deprecated.h" + +#include +#include "QtOpenGL/qgl.h" + +#include + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int main(int argc, char *argv[]) +{ + // It seems that if we are using paintEvent() instead of paintGL() to + // draw we might have to set OpenGL as the preferred paint engine + //QGL::setPreferredPaintEngine(QPaintEngine::OpenGL); + + QApplication app(argc, argv); + + // On Linux, Qt will use the system locale, force number formatting settings back to "C" locale + setlocale(LC_NUMERIC,"C"); + + QMVMainWindow_deprecated window; + QString platform = cvf::System::is64Bit() ? "(64bit)" : "(32bit)"; + window.setWindowTitle("Qt MultiView " + platform); + window.resize(1000, 800);; + window.show(); + + return app.exec(); +} diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVWidget_deprecated.cpp b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVWidget_deprecated.cpp new file mode 100644 index 0000000000..f52d2fab00 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVWidget_deprecated.cpp @@ -0,0 +1,247 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#include "cvfLibCore.h" +#include "cvfLibRender.h" +#include "cvfLibGeometry.h" +#include "cvfLibViewing.h" + +#include "QMVWidget_deprecated.h" + +#include + +using cvf::ref; + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMVWidget_deprecated::QMVWidget_deprecated(cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent) +: cvfqt::GLWidget_deprecated(contextGroup, format, parent) +{ + m_trackball = new cvf::ManipulatorTrackball; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMVWidget_deprecated::QMVWidget_deprecated(QMVWidget_deprecated* shareWidget, QWidget* parent) +: cvfqt::GLWidget_deprecated(shareWidget, parent) +{ + m_trackball = new cvf::ManipulatorTrackball; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QMVWidget_deprecated::~QMVWidget_deprecated() +{ + cvfShutdownOpenGLContext(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVWidget_deprecated::setRenderSequence(cvf::RenderSequence* renderSequence) +{ + m_trackball->setCamera(NULL); + m_renderSequence = renderSequence; + + if (m_renderSequence.notNull()) + { + // Camera extracted from first rendering of the view + cvf::Camera* camera = currentCamera(); + camera->viewport()->set(0, 0, width(), height()); + camera->setProjectionAsPerspective(camera->fieldOfViewYDeg(), camera->nearPlane(), camera->farPlane()); + + m_trackball->setCamera(camera); + + cvf::BoundingBox bb = m_renderSequence->boundingBox(); + if (bb.isValid()) + { + m_trackball->setRotationPoint(bb.center()); + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::RenderSequence* QMVWidget_deprecated::renderSequence() +{ + return m_renderSequence.p(); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVWidget_deprecated::resizeGL(int width, int height) +{ + cvf::Camera* camera = currentCamera(); + if (camera) + { + camera->viewport()->set(0, 0, width, height); + camera->setProjectionAsPerspective(camera->fieldOfViewYDeg(), camera->nearPlane(), camera->farPlane()); + } + else + { + glViewport(0, 0, width, height); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVWidget_deprecated::paintGL() +{ + cvf::OpenGLContext* currentOglContext = cvfOpenGLContext(); + CVF_ASSERT(currentOglContext); + CVF_CHECK_OGL(currentOglContext); + + cvf::OpenGLUtils::pushOpenGLState(currentOglContext); + + if (m_renderSequence.notNull()) + { + m_renderSequence->render(currentOglContext); + } + else + { + glClearColor(0.5f, 0.5f, 0.5f, 1.0f); + glClear(GL_COLOR_BUFFER_BIT); + } + + cvf::OpenGLUtils::popOpenGLState(currentOglContext); +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Camera* QMVWidget_deprecated::currentCamera() +{ + if (m_renderSequence.notNull()) + { + cvf::Rendering* rendering = m_renderSequence->firstRendering(); + if (rendering) + { + return rendering->camera(); + } + } + + return NULL; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVWidget_deprecated::mouseMoveEvent(QMouseEvent* event) +{ + if (m_renderSequence.isNull()) return; + + Qt::MouseButtons mouseBn = event->buttons(); + int posX = event->x(); + int posY = height() - event->y(); + + cvf::ManipulatorTrackball::NavigationType navType = cvf::ManipulatorTrackball::NONE; + if (mouseBn == Qt::LeftButton) + { + navType = cvf::ManipulatorTrackball::PAN; + } + else if (mouseBn == Qt::RightButton) + { + navType = cvf::ManipulatorTrackball::ROTATE; + } + else if (mouseBn == (Qt::LeftButton | Qt::RightButton) || mouseBn == Qt::MiddleButton) + { + navType = cvf::ManipulatorTrackball::WALK; + } + + if (navType != m_trackball->activeNavigation()) + { + m_trackball->startNavigation(navType, posX, posY); + } + + bool needRedraw = m_trackball->updateNavigation(posX, posY); + if (needRedraw) + { + update(); + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVWidget_deprecated::mousePressEvent(QMouseEvent* event) +{ + if (m_renderSequence.isNull()) return; + + if (event->buttons() == Qt::LeftButton && event->modifiers() == Qt::ControlModifier) + { + cvf::Rendering* r = m_renderSequence->firstRendering(); + ref ris = r->rayIntersectSpecFromWindowCoordinates(event->x(), height() - event->y()); + + cvf::HitItemCollection hic; + if (r->rayIntersect(*ris, &hic)) + { + cvf::HitItem* item = hic.firstItem(); + CVF_ASSERT(item && item->part()); + + cvf::Vec3d isect = item->intersectionPoint(); + m_trackball->setRotationPoint(isect); + + cvf::Trace::show("hitting part: '%s' coords: %.3f %.3f %.3f", item->part()->name().toAscii().ptr(), isect.x(), isect.y(), isect.z()); + } + } +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QMVWidget_deprecated::mouseReleaseEvent(QMouseEvent* /*event*/) +{ + m_trackball->endNavigation(); +} diff --git a/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVWidget_deprecated.h b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVWidget_deprecated.h new file mode 100644 index 0000000000..919be20086 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtMultiView_deprecated/QMVWidget_deprecated.h @@ -0,0 +1,77 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + + +#pragma once + +#include "cvfBase.h" +#include "cvfRenderSequence.h" +#include "cvfManipulatorTrackball.h" +#include "cvfqtGLWidget_deprecated.h" + + +//================================================================================================== +// +// +// +//================================================================================================== +class QMVWidget_deprecated : public cvfqt::GLWidget_deprecated +{ + Q_OBJECT + +public: + QMVWidget_deprecated(cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent); + QMVWidget_deprecated(QMVWidget_deprecated* shareWidget, QWidget* parent); + ~QMVWidget_deprecated(); + + void setRenderSequence(cvf::RenderSequence* renderSequence); + cvf::RenderSequence* renderSequence(); + +private: + void resizeGL(int width, int height); + void paintGL(); + + cvf::Camera* currentCamera(); + void mousePressEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event); + void mouseReleaseEvent(QMouseEvent* event); + +private: + cvf::ref m_renderSequence; + cvf::ref m_trackball; +}; + + diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt index 9f46f71802..e4e75b18b3 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/CMakeLists.txt @@ -35,6 +35,15 @@ QSRStdInclude.cpp QSRTranslateEvent.cpp ) +set(CEE_HEADER_FILES +QSRCommandLineArgs.h +QSRPropertiesPanel.h +QSRRunPanel.h +QSRSnippetWidget.h +QSRStdInclude.h +QSRTranslateEvent.h +) + # Headers that need MOCing set(MOC_HEADER_FILES QSRMainWindow.h @@ -43,8 +52,13 @@ QSRRunPanel.h QSRSnippetWidget.h ) + # Qt -if (CEE_USE_QT5) +if (CEE_USE_QT6) + find_package(Qt6 COMPONENTS REQUIRED OpenGLWidgets) + set(QT_LIBRARIES Qt6::OpenGLWidgets ) + qt_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) +elseif (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES} ) @@ -57,5 +71,5 @@ if (CMAKE_COMPILER_IS_GNUCXX) set(SYSTEM_LIBRARIES -lrt -lpthread) endif(CMAKE_COMPILER_IS_GNUCXX) -add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${MOC_SOURCE_FILES}) +add_executable(${PROJECT_NAME} ${CEE_SOURCE_FILES} ${CEE_HEADER_FILES} ${MOC_SOURCE_FILES}) target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ${SYSTEM_LIBRARIES}) diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRCommandLineArgs.h b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRCommandLineArgs.h index 11f303df27..d3854020d8 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRCommandLineArgs.h +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRCommandLineArgs.h @@ -37,7 +37,7 @@ #pragma once -class QStringList; +#include //================================================================================================== diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMain.cpp b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMain.cpp index b619acdb37..ddc8b6d38e 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMain.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMain.cpp @@ -60,9 +60,12 @@ int main(int argc, char *argv[]) // On Linux, Qt will use the system locale, force number formatting settings back to "C" locale setlocale(LC_NUMERIC,"C"); - // These directories are correct when running from within visual studio - cvf::String testDataDir = "../../../Tests/TestData/"; - cvf::String shaderDir = "../../../Tests/SnippetsBasis/Shaders/"; + cvf::String testDataDir = ""; + cvf::String shaderDir = ""; +#ifdef CVF_CEEVIZ_ROOT_SOURCE_DIR + testDataDir = CVF_CEEVIZ_ROOT_SOURCE_DIR "/Tests/TestData/"; + shaderDir = CVF_CEEVIZ_ROOT_SOURCE_DIR "/Tests/SnippetsBasis/Shaders/"; +#endif { QSRCommandLineArgs cmdLineArgs; @@ -95,6 +98,8 @@ int main(int argc, char *argv[]) // Comment in this line to be able to read the glsl directly from file //cvf::ShaderSourceProvider::instance()->setSourceRepository(new cvf::ShaderSourceRepositoryFile("../../../LibRender/glsl/")); + cvf::LogManager* logManager = cvf::LogManager::instance(); + logManager->logger("cee.cvf.OpenGL")->setLevel(cvf::Logger::LL_DEBUG); QSRMainWindow window; window.resize(1000, 800);; diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.cpp b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.cpp index c951740216..9707e3afd8 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRMainWindow.cpp @@ -127,7 +127,7 @@ void QSRMainWindow::createActions() } m_activateLastUsedSnippetAction = new QAction("Load last used snippet", this); - m_activateLastUsedSnippetAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L)); + m_activateLastUsedSnippetAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_L)); connect(m_activateLastUsedSnippetAction, SIGNAL(triggered()), SLOT(slotRunLastUsedSnippet())); m_closeCurrentSnippetAction = new QAction("Close Current Snippet", this); @@ -136,19 +136,19 @@ void QSRMainWindow::createActions() // View menu m_showHUDAction = new QAction("Show HUD", this); m_showHUDAction->setCheckable(true); - m_showHUDAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_H)); + m_showHUDAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_H)); connect(m_showHUDAction, SIGNAL(triggered()), SLOT(slotShowHUD())); m_redrawAction = new QAction("Redraw view", this); - m_redrawAction ->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_R)); + m_redrawAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_R)); connect(m_redrawAction, SIGNAL(triggered()), SLOT(slotViewRedraw())); m_multipleRedrawAction = new QAction("Redraw 10 times", this); - m_multipleRedrawAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_M)); + m_multipleRedrawAction->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_M)); connect(m_multipleRedrawAction, SIGNAL(triggered()), SLOT(slotViewMultipleRedraw())); m_multipleRedrawManyAction = new QAction("Redraw 50 times", this); - m_multipleRedrawManyAction->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_M)); + m_multipleRedrawManyAction->setShortcut(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_M)); connect(m_multipleRedrawManyAction, SIGNAL(triggered()), SLOT(slotViewMultipleRedrawMany())); @@ -302,8 +302,22 @@ void QSRMainWindow::createDockPanels() //-------------------------------------------------------------------------------------------------- void QSRMainWindow::executeTestSnippetInNewWidget(const cvf::String& snippetId, TestSnippet* snippet) { + cvf::Trace::show("Executing snippet: %s", snippetId.toAscii().ptr()); + closeCurrentSnippet(); + QWidget* parentWidget = centralWidget(); + CVF_ASSERT(m_contextGroup.notNull()); + +#ifdef QSR_USE_OPENGLWIDGET + + QSurfaceFormat surfFormat; + surfFormat.setSamples(m_formatMultisampleAction->isChecked() ? 8 : 0); + m_currentSnippetWidget = new QSRSnippetWidget(snippet, m_contextGroup.p(), parentWidget); + m_currentSnippetWidget->setFormat(surfFormat); + +#else + QGLFormat glFormat; glFormat.setDirectRendering(!m_formatSoftwareAction->isChecked()); @@ -320,9 +334,11 @@ void QSRMainWindow::executeTestSnippetInNewWidget(const cvf::String& snippetId, // For FSAA, use with glEnable(GL_MULTISAMPLE); //glFormat.setSampleBuffers(true); - QWidget* parentWidget = centralWidget(); - CVF_ASSERT(m_contextGroup.notNull()); m_currentSnippetWidget = new QSRSnippetWidget(snippet, m_contextGroup.p(), glFormat, parentWidget); + +#endif + + m_currentSnippetWidget->setFocus(); if (m_formatMultisampleAction->isChecked()) @@ -344,7 +360,7 @@ void QSRMainWindow::executeTestSnippetInNewWidget(const cvf::String& snippetId, // Store ID of this 'last run' snippet in registry QSettings settings("Ceetron", "SnippetRunner"); - settings.setValue("LastUsedSnippetID", snippetId.toAscii().ptr()); + settings.setValue("LastUsedSnippetID", cvfqt::Utils::toQString(snippetId)); repaint(); } @@ -537,6 +553,9 @@ void QSRMainWindow::slotViewMultipleRedrawMany() //-------------------------------------------------------------------------------------------------- void QSRMainWindow::slotSaveFrameBufferToFile() { +#ifdef QSR_USE_OPENGLWIDGET + cvf::Trace::show("NOT IMPLEMENTED!!"); +#else if (!m_currentSnippetWidget) { cvf::Trace::show("No current widget"); @@ -556,7 +575,7 @@ void QSRMainWindow::slotSaveFrameBufferToFile() { cvf::Trace::show("FAILED to saved image: %s", (const char*)fileName.toLatin1()); } - +#endif } @@ -740,32 +759,49 @@ void QSRMainWindow::slotShowHelp() } // OpenGL info + cvf::OpenGLContext* currentOglContext = m_currentSnippetWidget->cvfOpenGLContext(); + if (currentOglContext) { + cvf::OpenGLInfo cvfOglInfo = currentOglContext->group()->info(); oglInfo = QString("OpenGL info:"); - oglInfo += QString("\nversion:\t") + reinterpret_cast(glGetString(GL_VERSION)); - oglInfo += QString("\nrenderer:\t") + reinterpret_cast(glGetString(GL_RENDERER)); - oglInfo += QString("\nvendor:\t") + reinterpret_cast(glGetString(GL_VENDOR)); - oglInfo += QString("\nglsl ver.:\t") + reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); + oglInfo += QString("\nversion: ") + cvfqt::Utils::toQString(cvfOglInfo.version()); + oglInfo += QString("\nrenderer: ") + cvfqt::Utils::toQString(cvfOglInfo.renderer()); + oglInfo += QString("\nvendor: ") + cvfqt::Utils::toQString(cvfOglInfo.vendor()); } +#ifdef QSR_USE_OPENGLWIDGET { - oglInfo += "\n\nReported by Qt:"; - - QGLFormat currrentFormat = m_currentSnippetWidget->format(); + oglInfo += "\n\nReported by Qt QSurfaceFormat:"; + QSurfaceFormat currrentFormat = m_currentSnippetWidget->format(); oglInfo += QString("\nOpenGL version:\t%1.%2").arg(currrentFormat.majorVersion()).arg(currrentFormat.minorVersion()); - switch (currrentFormat.profile()) { - case QGLFormat::NoProfile: oglInfo += "\nProfile:\t\tNoProfile (GLver < 3.3)"; break; - case QGLFormat::CoreProfile: oglInfo += "\nProfile:\t\tCoreProfile"; break; - case QGLFormat::CompatibilityProfile: oglInfo += "\nProfile:\t\tCompatibilityProfile"; break; + case QSurfaceFormat::NoProfile: oglInfo += "\nProfile:NoProfile (GLver < 3.3)"; break; + case QSurfaceFormat::CoreProfile: oglInfo += "\nProfile:CoreProfile"; break; + case QSurfaceFormat::CompatibilityProfile: oglInfo += "\nProfile:CompatibilityProfile"; break; } - oglInfo += QString("\nColor buffer size:\t<%1 %2 %3 %4>").arg(currrentFormat.redBufferSize()).arg(currrentFormat.greenBufferSize()).arg(currrentFormat.blueBufferSize()).arg(currrentFormat.alphaBufferSize()); - oglInfo += QString("\nDepth buffer size:\t%1").arg(currrentFormat.depthBufferSize()); + oglInfo += QString("\nColor buffer size:<%1 %2 %3 %4>").arg(currrentFormat.redBufferSize()).arg(currrentFormat.greenBufferSize()).arg(currrentFormat.blueBufferSize()).arg(currrentFormat.alphaBufferSize()); + oglInfo += QString("\nDepth buffer size:%1").arg(currrentFormat.depthBufferSize()); } +#else + { + oglInfo += "\n\nReported by Qt QGLFormat:"; + + QGLFormat currrentFormat = m_currentSnippetWidget->format(); + oglInfo += QString("\nOpenGL version:\t%1.%2").arg(currrentFormat.majorVersion()).arg(currrentFormat.minorVersion()); + switch (currrentFormat.profile()) + { + case QGLFormat::NoProfile: oglInfo += "\nProfile:NoProfile (GLver < 3.3)"; break; + case QGLFormat::CoreProfile: oglInfo += "\nProfile:CoreProfile"; break; + case QGLFormat::CompatibilityProfile: oglInfo += "\nProfile:CompatibilityProfile"; break; + } + oglInfo += QString("\nColor buffer size:<%1 %2 %3 %4>").arg(currrentFormat.redBufferSize()).arg(currrentFormat.greenBufferSize()).arg(currrentFormat.blueBufferSize()).arg(currrentFormat.alphaBufferSize()); + oglInfo += QString("\nDepth buffer size:%1").arg(currrentFormat.depthBufferSize()); + } +#endif } QMessageBox dlg(this); diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.cpp b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.cpp index d8352af623..e6d00cc8ce 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.cpp @@ -40,10 +40,10 @@ #include "QSRTranslateEvent.h" #include "cvfqtPerformanceInfoHud.h" -#include "cvfqtOpenGLContext.h" #include +#include #include using cvfu::TestSnippet; @@ -53,8 +53,13 @@ using cvfu::TestSnippet; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- +#ifdef QSR_USE_OPENGLWIDGET +QSRSnippetWidget::QSRSnippetWidget(TestSnippet* snippet, cvf::OpenGLContextGroup* contextGroup, QWidget* parent) +: OglWidgetBaseClass(contextGroup, parent), +#else QSRSnippetWidget::QSRSnippetWidget(TestSnippet* snippet, cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent) -: cvfqt::OpenGLWidget(contextGroup, format, parent), +: OglWidgetBaseClass(contextGroup, format, parent), +#endif m_drawHUD(false), m_lastSetRenderMode(DrawableGeo::VERTEX_ARRAY), m_enableMultisampleWhenDrawing(false) @@ -88,8 +93,6 @@ QSRSnippetWidget::~QSRSnippetWidget() m_snippet->destroySnippet(); m_snippet = NULL; } - - cvfShutdownOpenGLContext(); } @@ -526,6 +529,8 @@ void QSRSnippetWidget::showModelStatistics() //-------------------------------------------------------------------------------------------------- void QSRSnippetWidget::initializeGL() { + OglWidgetBaseClass::initializeGL(); + CVF_ASSERT(m_snippet.notNull()); cvf::OpenGLContext* currentOglContext = cvfOpenGLContext(); @@ -534,6 +539,7 @@ void QSRSnippetWidget::initializeGL() bool bInitOK = m_snippet->initializeSnippet(currentOglContext); CVF_ASSERT(bInitOK); + CVF_UNUSED(bInitOK); CVF_CHECK_OGL(currentOglContext); @@ -595,7 +601,7 @@ void QSRSnippetWidget::paintEvent(QPaintEvent* /*event*/) painter.beginNativePainting(); CVF_CHECK_OGL(currentOglContext); - cvfqt::OpenGLContext::saveOpenGLState(currentOglContext); + cvf::OpenGLUtils::pushOpenGLState(currentOglContext); CVF_CHECK_OGL(currentOglContext); if (m_enableMultisampleWhenDrawing) @@ -612,7 +618,7 @@ void QSRSnippetWidget::paintEvent(QPaintEvent* /*event*/) glDisable(GL_MULTISAMPLE); } - cvfqt::OpenGLContext::restoreOpenGLState(currentOglContext); + cvf::OpenGLUtils::popOpenGLState(currentOglContext); CVF_CHECK_OGL(currentOglContext); if (postEventAction == cvfu::REDRAW) diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.h b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.h index 9a74e7f514..b80f975934 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.h +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRSnippetWidget.h @@ -45,22 +45,35 @@ #include "cvfuTestSnippet.h" -#include "cvfqtOpenGLWidget.h" - class QTimer; +#define QSR_USE_OPENGLWIDGET + +#ifdef QSR_USE_OPENGLWIDGET +#include "cvfqtOpenGLWidget.h" +typedef cvfqt::OpenGLWidget OglWidgetBaseClass; +#else +#include "cvfqtGLWidget.h" +typedef cvfqt::GLWidget OglWidgetBaseClass; +#endif + + //================================================================================================== // // // //================================================================================================== -class QSRSnippetWidget : public cvfqt::OpenGLWidget +class QSRSnippetWidget : public OglWidgetBaseClass { Q_OBJECT public: +#ifdef QSR_USE_OPENGLWIDGET + QSRSnippetWidget(cvfu::TestSnippet* snippet, cvf::OpenGLContextGroup* contextGroup, QWidget* parent); +#else QSRSnippetWidget(cvfu::TestSnippet* snippet, cvf::OpenGLContextGroup* contextGroup, const QGLFormat& format, QWidget* parent); +#endif ~QSRSnippetWidget(); cvfu::TestSnippet* snippet(); diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRTranslateEvent.cpp b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRTranslateEvent.cpp index d69c6a21f0..a088561cd4 100644 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRTranslateEvent.cpp +++ b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/QSRTranslateEvent.cpp @@ -51,7 +51,7 @@ cvfu::MouseEvent QSRTranslateEvent::translateMouseEvent(int widgetHeight, const Qt::MouseButtons qtButtons = event.buttons(); cvfu::MouseButtons buttons = cvfu::NoButton; if (qtButtons & Qt::LeftButton) buttons |= cvfu::LeftButton; - if (qtButtons & Qt::MidButton) buttons |= cvfu::MiddleButton; + if (qtButtons & Qt::MiddleButton) buttons |= cvfu::MiddleButton; if (qtButtons & Qt::RightButton) buttons |= cvfu::RightButton; Qt::KeyboardModifiers qtModifiers = event.modifiers(); @@ -69,7 +69,7 @@ cvfu::MouseEvent QSRTranslateEvent::translateMouseEvent(int widgetHeight, const cvfu::MouseButton QSRTranslateEvent::translateMouseButton(Qt::MouseButton qtMouseButton) { if (qtMouseButton == Qt::LeftButton) return cvfu::LeftButton; - if (qtMouseButton == Qt::MidButton) return cvfu::MiddleButton; + if (qtMouseButton == Qt::MiddleButton) return cvfu::MiddleButton; if (qtMouseButton == Qt::RightButton) return cvfu::RightButton; return cvfu::NoButton; diff --git a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/TriggerTBBCopy.txt b/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/TriggerTBBCopy.txt deleted file mode 100644 index bf816d39e4..0000000000 --- a/Fwk/VizFwk/TestApps/Qt/QtSnippetRunner/TriggerTBBCopy.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Sole purpose of this file is to have custom build rules to trigger copying of TBB DLLs diff --git a/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/CMakeLists.txt b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/CMakeLists.txt new file mode 100644 index 0000000000..9cf439ac77 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/CMakeLists.txt @@ -0,0 +1,58 @@ +project(QtTestBenchOpenGLWidget) + + +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CEE_STANDARD_CXX_FLAGS}") + +if (CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long") +endif() + + +find_package(OpenGL) + +if (CEE_USE_QT6) + find_package(Qt6 COMPONENTS REQUIRED OpenGLWidgets) + set(QT_LIBRARIES Qt6::OpenGLWidgets ) +elseif (CEE_USE_QT5) + find_package(Qt5 REQUIRED COMPONENTS Widgets) + set(QT_LIBRARIES Qt5::Widgets) +else() + message(FATAL_ERROR "No supported Qt version selected for build") +endif() + + +include_directories(${LibCore_SOURCE_DIR}) +include_directories(${LibGeometry_SOURCE_DIR}) +include_directories(${LibRender_SOURCE_DIR}) +include_directories(${LibViewing_SOURCE_DIR}) +include_directories(${LibUtilities_SOURCE_DIR}) +include_directories(${LibGuiQt_SOURCE_DIR}) + +set(CEE_LIBS LibGuiQt LibUtilities LibViewing LibRender LibGeometry LibIo LibCore) + + +set(CEE_CODE_FILES +QTBMain.cpp +QTBMainWindow.cpp +QTBMainWindow.h +QTBSceneFactory.cpp +QTBSceneFactory.h +QTBVizWidget.cpp +QTBVizWidget.h +) + +# Headers that need MOCing +set(MOC_HEADER_FILES +QTBMainWindow.h +QTBVizWidget.h +) + +if (CEE_USE_QT6) + qt_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) +elseif (CEE_USE_QT5) + qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) +endif() + +add_executable(${PROJECT_NAME} ${CEE_CODE_FILES} ${MOC_SOURCE_FILES}) +target_link_libraries(${PROJECT_NAME} ${CEE_LIBS} ${OPENGL_LIBRARIES} ${QT_LIBRARIES}) + diff --git a/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBMain.cpp b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBMain.cpp new file mode 100644 index 0000000000..cb61b3eab5 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBMain.cpp @@ -0,0 +1,103 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#include "cvfLibCore.h" +#include "cvfLibRender.h" +#include "cvfLibGeometry.h" +#include "cvfLibViewing.h" + +#include + +#include "QTBMainWindow.h" + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int main(int argc, char* argv[]) +{ + // Used to get registry settings in the right place + QCoreApplication::setOrganizationName("CeetronSolutions"); + QCoreApplication::setApplicationName("QtTestBenchOpenGLWidget"); + + // Note! + // The Qt::AA_ShareOpenGLContexts setting is needed when we have multiple viz widgets in flight + // and we have a setup where these widgets belong to different top-level windows, or end up + // belonging to different top-level windows through re-parenting. + // This is indeed the situation we encounter in this test application. + // For example: + // * Two viz widgets inside the same central widget => OK + // * Two viz widgets docked inside two different dock widgets => OK + // * One viz widget in docked dock widget and one viz widget in central widget => OK + // * Two viz widgets as different top level windows => FAIL + // * One viz widget in docked dock widget and one viz widget in floating dock widget => FAIL + // * One viz widget in central widget and one widget as top level window => FAIL + // + // In the failing situations the viz widgets should really belong to different context groups (which + // has it own implications), but as a workaround we can use the Qt::AA_ShareOpenGLContexts flag + QApplication::setAttribute(Qt::AA_ShareOpenGLContexts); + + // May want to do some further experimentation with these as well + //QApplication::setAttribute(Qt::AA_NativeWindows); + //QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + + //QApplication::setAttribute(Qt::AA_UseDesktopOpenGL); + //QApplication::setAttribute(Qt::AA_UseSoftwareOpenGL); + //QApplication::setAttribute(Qt::AA_UseOpenGLES); + + + cvf::LogManager* logManager = cvf::LogManager::instance(); + logManager->logger("cee.cvf.OpenGL")->setLevel(cvf::Logger::LL_DEBUG); + + // To display logging from GLWidget::logOpenGLInfo() + logManager->logger("cee.cvf.qt")->setLevel(cvf::Logger::LL_INFO); + + // For even more output + logManager->logger("cee.cvf.qt")->setLevel(cvf::Logger::LL_DEBUG); + + + QApplication app(argc, argv); + + QTBMainWindow mainWindow; + mainWindow.setWindowTitle(QString("QtTestBenchOpenGLWidget (qtVer=%1)").arg(qVersion())); + mainWindow.resize(1000, 800); + mainWindow.show(); + + const int appRetCode = app.exec(); + return appRetCode; +} + diff --git a/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBMainWindow.cpp b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBMainWindow.cpp new file mode 100644 index 0000000000..2ed8d44a71 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBMainWindow.cpp @@ -0,0 +1,676 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#include "cvfLibCore.h" +#include "cvfLibRender.h" +#include "cvfLibGeometry.h" +#include "cvfLibViewing.h" + +#include "QTBMainWindow.h" +#include "QTBVizWidget.h" +#include "QTBSceneFactory.h" + +#include "cvfqtUtils.h" + +#include +#include +#include +#include +#include +#include +#include + + +//================================================================================================== +// +// +// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QTBMainWindow::QTBMainWindow() +{ + QFrame* mainFrame = new QFrame(this); + QVBoxLayout* layout = new QVBoxLayout(mainFrame); + mainFrame->setLayout(layout); + setCentralWidget(mainFrame); + + m_dockWidget_1 = new QDockWidget("MyDockWidget_1", this); + m_dockWidget_1->setObjectName("myDockWidget_1"); + addDockWidget(Qt::LeftDockWidgetArea, m_dockWidget_1); + + m_dockWidget_2 = new QDockWidget("MyDockWidget_2", this); + m_dockWidget_2->setObjectName("myDockWidget_2"); + addDockWidget(Qt::LeftDockWidgetArea, m_dockWidget_2); + + resizeDocks({ m_dockWidget_1, m_dockWidget_2 }, { 200, 200 }, Qt::Horizontal); + //loadWinGeoAndDockToolBarLayout(); + + + // The common context group must be created before launching any widgets + // If we don't create one, each widget will get its own context group + m_commonContextGroup = new cvf::OpenGLContextGroup; + + addVizWidget(AddToCentralWidget); + addVizWidget(InDockWidget_1); + addVizWidget(InDockWidget_2); + addVizWidget(AsNewTopLevelWidget); + + { + QMenu* menu = menuBar()->addMenu("&Widgets"); + menu->addAction("Add VizWidget into CentralWidget", this, SLOT(slotAddVizWidget()))->setData(AddToCentralWidget); + menu->addAction("Add VizWidget as TopLevel", this, SLOT(slotAddVizWidget()))->setData(AsNewTopLevelWidget); + menu->addAction("Add VizWidget into DockWidget_1", this, SLOT(slotAddVizWidget()))->setData(InDockWidget_1); + menu->addAction("Add VizWidget into DockWidget_2", this, SLOT(slotAddVizWidget()))->setData(InDockWidget_2); + + menu->addSeparator(); + menu->addAction("Delete VizWidget", this, SLOT(slotDeleteVizWidget())); + + menu->addSeparator(); + menu->addAction("Reparent VizWidget into CentralWidget", this, SLOT(slotReparentVizWidgetIntoCentralWidget())); + menu->addAction("Reparent VizWidget as Top Level", this, SLOT(slotReparentVizWidgetAsTopLevel())); + menu->addAction("Move VizWidget to DockWidget_1", this, SLOT(slotMoveVizWidgetToDockWidget_1())); + menu->addAction("Move VizWidget to DockWidget_2", this, SLOT(slotMoveVizWidgetToDockWidget_2())); + menu->addSeparator(); + menu->addAction("Reparent ALL VizWidgets into CentralWidget", this, SLOT(slotReparentAllVizWidgetsIntoCentralWidget())); + + menu->addSeparator(); + menu->addAction("Refresh VizWidget arr", this, SLOT(slotRefreshVizWidgetArr())); + } + { + QMenu* menu = menuBar()->addMenu("&Activate"); + connect(menu, SIGNAL(aboutToShow()), SLOT(slotAboutToShowActivateMenu())); + } + { + QMenu* menu = menuBar()->addMenu("&Scenes"); + + menu->addAction("Create test scene", this, SLOT(slotCreateTestScene())); + menu->addAction("Clear scene", this, SLOT(slotClearScene())); + } + { + QMenu* menu = menuBar()->addMenu("&Test"); + + menu->addAction("Save layout", this, SLOT(slotSaveLayout())); + menu->addAction("Restore layout", this, SLOT(slotRestoreLayout())); + menu->addSeparator(); + menu->addAction("Grab a native handle", this, SLOT(slotGrabNativeHandle())); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QTBMainWindow::~QTBMainWindow() +{ + cvf::Trace::show("QTBMainWindow::~QTBMainWindow()"); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::addVizWidget(NewWidgetPlacement newWidgetPlacement) +{ + // Guard against creating duplicate viewers inside dock widgets + if (newWidgetPlacement == InDockWidget_1 && m_dockWidget_1->widget()) + { + cvf::Trace::show("DockWidget_1 already contains a viewer"); + return; + } + if (newWidgetPlacement == InDockWidget_2 && m_dockWidget_2->widget()) + { + cvf::Trace::show("DockWidget_2 already contains a viewer"); + return; + } + + removeStaleEntriesFromVizWidgetArr(); + + QWidget* parentToUseOnConstruction = this; + //QWidget* parentToUseOnConstruction = NULL; + + // Use the common context group if we have one - otherwise create a new context group per widget + cvf::ref contextGroupToUse = m_commonContextGroup; + if (contextGroupToUse.isNull()) + { + contextGroupToUse = new cvf::OpenGLContextGroup; + } + + QTBVizWidget* newVizWidget = newVizWidget = new QTBVizWidget(contextGroupToUse.p(), parentToUseOnConstruction, this); + + m_vizWidgetArr.push_back(newVizWidget); + + // Place the widget where instructed + if (newWidgetPlacement == AddToCentralWidget) + { + centralWidget()->layout()->addWidget(newVizWidget); + } + else if (newWidgetPlacement == AsNewTopLevelWidget) + { + newVizWidget->setParent(nullptr); + newVizWidget->resize(400, 300); + newVizWidget->move(50, 200); + newVizWidget->show(); + } + else if (newWidgetPlacement == InDockWidget_1) + { + m_dockWidget_1->setWidget(newVizWidget); + newVizWidget->show(); + } + else if (newWidgetPlacement == InDockWidget_2) + { + m_dockWidget_2->setWidget(newVizWidget); + newVizWidget->show(); + } + + assignViewTitlesToVizWidgetsInArr(); + decideNewActiveVizWidgetAndHighlight(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::handleVizWidgetIsOpenGLReady(QTBVizWidget* vizWidget) +{ + cvf::Trace::show("QTBMainWindow::handleVizWidgetIsOpenGLReady()"); + + CVF_ASSERT(vizWidget->isValid()); + cvf::OpenGLContext* oglContext = vizWidget->cvfOpenGLContext(); + cvf::OpenGLContextGroup* oglContextGroup = oglContext->group(); + CVF_ASSERT(oglContextGroup->isContextGroupInitialized()); + + if (m_commonContextGroup.notNull()) + { + CVF_ASSERT(m_commonContextGroup == oglContextGroup); + CVF_ASSERT(m_commonContextGroup->containsContext(oglContext)); + populateAllValidVizWidgetsWithTestScene(true); + } + else + { + populateAllValidVizWidgetsWithTestScene(false); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::populateAllValidVizWidgetsWithTestScene(bool allWidgetsShareSameScene) +{ + if (allWidgetsShareSameScene) + { + cvf::ref sceneToShow; + + // Look for an existing scene + for (auto vizWidget : m_vizWidgetArr) + { + if (vizWidget->isValid() && vizWidget->scene()) + { + sceneToShow = vizWidget->scene(); + break; + } + } + + if (sceneToShow.isNull()) + { + QTBVizWidget* firstValidVizWidget = nullptr; + for (auto vizWidget : m_vizWidgetArr) + { + if (vizWidget->isValid()) + { + firstValidVizWidget = vizWidget; + break; + } + } + + if (!firstValidVizWidget) + { + cvf::Trace::show("Could not find any valid VizWidgets"); + return; + } + + cvf::OpenGLContext* oglContext = firstValidVizWidget->cvfOpenGLContext(); + CVF_ASSERT(oglContext); + const cvf::OpenGLCapabilities capabilities = *(oglContext->capabilities()); + const bool useShaders = capabilities.supportsOpenGL2(); + QTBSceneFactory sceneFactory(useShaders); + sceneToShow = sceneFactory.createTestScene(capabilities); + } + + for (auto vizWidget : m_vizWidgetArr) + { + vizWidget->setScene(sceneToShow.p()); + vizWidget->update(); + } + } + else + { + for (auto vizWidget : m_vizWidgetArr) + { + if (vizWidget->isValid() && !vizWidget->scene()) + { + cvf::OpenGLContext* oglContext = vizWidget->cvfOpenGLContext(); + CVF_ASSERT(oglContext); + const cvf::OpenGLCapabilities capabilities = *(oglContext->capabilities()); + const bool useShaders = capabilities.supportsOpenGL2(); + QTBSceneFactory sceneFactory(useShaders); + cvf::ref scene = sceneFactory.createTestScene(capabilities); + + vizWidget->setScene(scene.p()); + vizWidget->update(); + } + } + } +} + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::removeStaleEntriesFromVizWidgetArr() +{ + std::vector > oldArr = m_vizWidgetArr; + m_vizWidgetArr.clear(); + + for (size_t i = 0; i < oldArr.size(); i++) + { + QTBVizWidget* vizWidget = oldArr[i]; + if (vizWidget) + { + m_vizWidgetArr.push_back(vizWidget); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::assignViewTitlesToVizWidgetsInArr() +{ + for (size_t i = 0; i < m_vizWidgetArr.size(); i++) + { + QTBVizWidget* vizWidget = m_vizWidgetArr[i]; + if (vizWidget) + { + vizWidget->setViewTitle(cvf::String("view_%1").arg(static_cast(i))); + vizWidget->update(); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector QTBMainWindow::vizWidgetNames() +{ + std::vector nameArr; + for (auto vizWidget : m_vizWidgetArr) + { + nameArr.push_back(vizWidget->viewTitle()); + } + + return nameArr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::decideNewActiveVizWidgetAndHighlight() +{ + // For now, simply choose the last one + m_activeVizWidgetName = ""; + const std::vector nameArr = vizWidgetNames(); + if (nameArr.size() > 0) + { + m_activeVizWidgetName = nameArr.back(); + } + + highlightActiveVizWidget(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::highlightActiveVizWidget() +{ + for (auto vizWidget : m_vizWidgetArr) + { + const bool isActive = vizWidget->viewTitle() == m_activeVizWidgetName; + vizWidget->setViewTitleHighlighted(isActive); + vizWidget->update(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QTBVizWidget* QTBMainWindow::getActiveVizWidget() +{ + if (m_vizWidgetArr.size() == 0) + { + cvf::Trace::show("Could not get active VizWidget, no widgets present"); + return nullptr; + } + + for (auto vizWidget : m_vizWidgetArr) + { + if (vizWidget->viewTitle() == m_activeVizWidgetName) + { + return vizWidget; + } + } + + return nullptr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::saveWinGeoAndDockToolBarLayout() +{ + QSettings settings; + settings.setValue("winGeometry", saveGeometry()); + settings.setValue("dockAndToolBarLayout", saveState(0)); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::loadWinGeoAndDockToolBarLayout() +{ + QSettings settings; + QVariant winGeo = settings.value("winGeometry"); + QVariant layout = settings.value("dockAndToolBarLayout"); + + if (winGeo.isValid()) + { + if (restoreGeometry(winGeo.toByteArray())) + { + if (layout.isValid()) + { + restoreState(layout.toByteArray(), 0); + } + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::closeEvent(QCloseEvent* event) +{ + cvf::Trace::show("QTBMainWindow::closeEvent()"); + QMainWindow::closeEvent(event); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotAddVizWidget() +{ + QAction* senderAction = dynamic_cast(sender()); + const int newWidgetPlacementInt = senderAction->data().toInt(); + NewWidgetPlacement newWidgetPlacement = static_cast(newWidgetPlacementInt); + + addVizWidget(newWidgetPlacement); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotDeleteVizWidget() +{ + removeStaleEntriesFromVizWidgetArr(); + + QTBVizWidget* vizWidget = getActiveVizWidget(); + if (!vizWidget) + { + return; + } + + delete vizWidget; + + removeStaleEntriesFromVizWidgetArr(); + assignViewTitlesToVizWidgetsInArr(); + decideNewActiveVizWidgetAndHighlight(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotReparentVizWidgetIntoCentralWidget() +{ + QTBVizWidget* vizWidget = getActiveVizWidget(); + if (!vizWidget) + { + return; + } + + CVF_ASSERT(vizWidget->isValid()); + + centralWidget()->layout()->addWidget(vizWidget); + vizWidget->show(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotReparentVizWidgetAsTopLevel() +{ + QTBVizWidget* vizWidget = getActiveVizWidget(); + if (!vizWidget) + { + return; + } + + CVF_ASSERT(vizWidget->isValid()); + + vizWidget->setParent(nullptr); + vizWidget->move(100, 100); + vizWidget->resize(600, 400); + vizWidget->show(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotMoveVizWidgetToDockWidget_1() +{ + if (m_dockWidget_1->widget()) + { + cvf::Trace::show("DockWidget_1 already contains a vizWiget"); + return; + } + + QTBVizWidget* vizWidget = getActiveVizWidget(); + if (!vizWidget) + { + return; + } + + CVF_ASSERT(vizWidget->isValid()); + + m_dockWidget_1->setWidget(vizWidget); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotMoveVizWidgetToDockWidget_2() +{ + if (m_dockWidget_2->widget()) + { + cvf::Trace::show("DockWidget_2 already contains a vizWiget"); + return; + } + + QTBVizWidget* vizWidget = getActiveVizWidget(); + if (!vizWidget) + { + return; + } + + CVF_ASSERT(vizWidget->isValid()); + + m_dockWidget_2->setWidget(vizWidget); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotReparentAllVizWidgetsIntoCentralWidget() +{ + for (size_t i = 0; i < m_vizWidgetArr.size(); i++) + { + QTBVizWidget* vizWidget = m_vizWidgetArr[i]; + if (vizWidget) + { + centralWidget()->layout()->addWidget(vizWidget); + vizWidget->show(); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotRefreshVizWidgetArr() +{ + const size_t numWidgetsBefore = m_vizWidgetArr.size(); + + removeStaleEntriesFromVizWidgetArr(); + assignViewTitlesToVizWidgetsInArr(); + + const size_t numWidgetsAfter = m_vizWidgetArr.size(); + + cvf::Trace::show("Refreshed VizWidgetArr, oldCount=%d newCount=%d", numWidgetsBefore, numWidgetsAfter); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotAboutToShowActivateMenu() +{ + QMenu* senderMenu = dynamic_cast(sender()); + CVF_ASSERT(senderMenu); + senderMenu->clear(); + + const std::vector nameArr = vizWidgetNames(); + for (auto widgetName : nameArr) + { + const QString qstrWidgetName(cvfqt::Utils::toQString(widgetName)); + senderMenu->addAction(qstrWidgetName, this, SLOT(slotSomeVizWidgetActivated()))->setData(qstrWidgetName); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotSomeVizWidgetActivated() +{ + QAction* senderAction = dynamic_cast(sender()); + CVF_ASSERT(senderAction); + const QString qstrWidgetName = senderAction->data().toString(); + m_activeVizWidgetName = cvfqt::Utils::toString(qstrWidgetName); + + highlightActiveVizWidget(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotCreateTestScene() +{ + if (m_vizWidgetArr.size() == 0) + { + return; + } + + const bool allWidgetsShareSameScene = m_commonContextGroup.notNull() ? true : false; + populateAllValidVizWidgetsWithTestScene(allWidgetsShareSameScene); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotClearScene() +{ + for (size_t i = 0; i < m_vizWidgetArr.size(); i++) + { + QTBVizWidget* vizWidget = m_vizWidgetArr[i]; + CVF_ASSERT(vizWidget); + vizWidget->setScene(nullptr); + vizWidget->update(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotSaveLayout() +{ + saveWinGeoAndDockToolBarLayout(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotRestoreLayout() +{ + loadWinGeoAndDockToolBarLayout(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBMainWindow::slotGrabNativeHandle() +{ + QTBVizWidget* vizWidget = getActiveVizWidget(); + if (!vizWidget) + { + return; + } + + CVF_ASSERT(vizWidget->isValid()); + cvf::String vizWidgetName = vizWidget->viewTitle(); + cvf::Trace::show("Trying to get native handle for %s by calling QWidget::winId()", vizWidgetName.toAscii().ptr()); + + // Calling this seems to wreak havoc for Qt itself. + // For Qt5 it seems that under certain circumstances it will work, BUT for Qt6 it basically breaks the entire app + WId theWinId = vizWidget->winId(); + cvf::Trace::show("Got WinId = 0x%x", (cvf::uint64)(theWinId)); +} + diff --git a/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBMainWindow.h b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBMainWindow.h new file mode 100644 index 0000000000..b2a75f87e2 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBMainWindow.h @@ -0,0 +1,118 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" + +#include "QTBVizWidget.h" + +#include +#include + + + +//================================================================================================== +// +// +// +//================================================================================================== +class QTBMainWindow : public QMainWindow +{ + Q_OBJECT + +public: + QTBMainWindow(); + ~QTBMainWindow(); + + void handleVizWidgetIsOpenGLReady(QTBVizWidget* vizWidget); + +private: + enum NewWidgetPlacement + { + AddToCentralWidget, + AsNewTopLevelWidget, + InDockWidget_1, + InDockWidget_2 + }; + +private: + void addVizWidget(NewWidgetPlacement newWidgetPlacement); + void populateAllValidVizWidgetsWithTestScene(bool allWidgetsShareSameScene); + void removeStaleEntriesFromVizWidgetArr(); + void assignViewTitlesToVizWidgetsInArr(); + std::vector vizWidgetNames(); + void decideNewActiveVizWidgetAndHighlight(); + void highlightActiveVizWidget(); + QTBVizWidget* getActiveVizWidget(); + void saveWinGeoAndDockToolBarLayout(); + void loadWinGeoAndDockToolBarLayout(); + + virtual void closeEvent(QCloseEvent* event); + +private slots: + void slotAddVizWidget(); + void slotDeleteVizWidget(); + void slotReparentVizWidgetIntoCentralWidget(); + void slotReparentVizWidgetAsTopLevel(); + void slotMoveVizWidgetToDockWidget_1(); + void slotMoveVizWidgetToDockWidget_2(); + void slotReparentAllVizWidgetsIntoCentralWidget(); + void slotRefreshVizWidgetArr(); + + void slotAboutToShowActivateMenu(); + void slotSomeVizWidgetActivated(); + + void slotCreateTestScene(); + void slotClearScene(); + + void slotSaveLayout(); + void slotRestoreLayout(); + void slotGrabNativeHandle(); + +private: + cvf::ref m_commonContextGroup; + std::vector> m_vizWidgetArr; + cvf::String m_activeVizWidgetName; + + QPointer m_dockWidget_1; + QPointer m_dockWidget_2; + + QPointer m_setWorkingVizWidgetFirstAction; + QPointer m_setWorkingVizWidgetLastAction; +}; + diff --git a/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBSceneFactory.cpp b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBSceneFactory.cpp new file mode 100644 index 0000000000..8ee8858476 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBSceneFactory.cpp @@ -0,0 +1,291 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#include "cvfLibCore.h" +#include "cvfLibRender.h" +#include "cvfLibGeometry.h" +#include "cvfLibViewing.h" + +#include "QTBSceneFactory.h" + + + + +//================================================================================================== +// +// +// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QTBSceneFactory::QTBSceneFactory(bool useShaders) +: m_useShaders(useShaders) +{ +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref QTBSceneFactory::createTestScene(const cvf::OpenGLCapabilities& capabilities) const +{ + cvf::ref model = new cvf::ModelBasicList; + + cvf::ShaderProgramGenerator spGen("MyStandardHeadlight", cvf::ShaderSourceProvider::instance()); + spGen.configureStandardHeadlightColor(); + cvf::ref shaderProg = spGen.generate(); + + { + cvf::GeometryBuilderDrawableGeo builder; + cvf::GeometryUtils::createSphere(2, 10, 10, &builder); + + cvf::ref eff = new cvf::Effect; + if (m_useShaders) + { + eff->setShaderProgram(shaderProg.p()); + eff->setUniform(new cvf::UniformFloat("u_color", cvf::Color4f(cvf::Color3::GREEN))); + } + else + { + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::BLUE)); + } + + cvf::ref part = new cvf::Part; + part->setName("MySphere"); + part->setDrawable(0, builder.drawableGeo().p()); + part->setEffect(eff.p()); + + model->addPart(part.p()); + } + + { + cvf::GeometryBuilderDrawableGeo builder; + cvf::GeometryUtils::createBox(cvf::Vec3f(5, 0, 0), 2, 3, 4, &builder); + + cvf::ref eff = new cvf::Effect; + if (m_useShaders) + { + eff->setShaderProgram(shaderProg.p()); + eff->setUniform(new cvf::UniformFloat("u_color", cvf::Color4f(cvf::Color3::YELLOW))); + } + else + { + eff->setRenderState(new cvf::RenderStateMaterial_FF(cvf::Color3::RED)); + } + + cvf::ref part = new cvf::Part; + part->setName("MyBox"); + part->setDrawable(0, builder.drawableGeo().p()); + part->setEffect(eff.p()); + + model->addPart(part.p()); + } + + + model->addPart(createTexturedPart(capabilities).p()); + + model->addPart(createDrawableTextPart(capabilities).p()); + + model->updateBoundingBoxesRecursive(); + + cvf::ref scene = new cvf::Scene; + scene->addModel(model.p()); + + return scene; +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref QTBSceneFactory::createQuadGeoWithTexCoords(const cvf::Vec3f& origin, const cvf::Vec3f& u, const cvf::Vec3f& v) +{ + cvf::ref vertices = new cvf::Vec3fArray(4); + vertices->set(0, origin); + vertices->set(1, origin + u); + vertices->set(2, origin + u + v); + vertices->set(3, origin + v); + + cvf::ref texCoords = new cvf::Vec2fArray(4); + texCoords->set(0, cvf::Vec2f(0, 0)); + texCoords->set(1, cvf::Vec2f(1, 0)); + texCoords->set(2, cvf::Vec2f(1, 1)); + texCoords->set(3, cvf::Vec2f(0, 1)); + + const cvf::uint conns[6] = { 0, 1, 2, 0, 2, 3}; + cvf::ref indices = new cvf::UIntArray(conns, 6); + + cvf::ref primSet = new cvf::PrimitiveSetIndexedUInt(cvf::PT_TRIANGLES); + primSet->setIndices(indices.p()); + + cvf::ref geo = new cvf::DrawableGeo; + geo->setVertexArray(vertices.p()); + geo->setTextureCoordArray(texCoords.p()); + geo->addPrimitiveSet(primSet.p()); + + geo->computeNormals(); + + return geo; + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref QTBSceneFactory::create4x4ColoredImage() +{ + // Create a simple 4x4 texture with 16 unique colors + cvf::ref textureImage = new cvf::TextureImage; + + { + cvf::ref textureData = new cvf::Color4ubArray; + textureData->reserve(16); + textureData->add(cvf::Color4ub(cvf::Color3::RED)); + textureData->add(cvf::Color4ub(cvf::Color3::GREEN)); + textureData->add(cvf::Color4ub(cvf::Color3::BLUE)); + textureData->add(cvf::Color4ub(cvf::Color3::YELLOW)); + textureData->add(cvf::Color4ub(cvf::Color3::CYAN)); + textureData->add(cvf::Color4ub(cvf::Color3::MAGENTA)); + textureData->add(cvf::Color4ub(cvf::Color3::INDIGO)); + textureData->add(cvf::Color4ub(cvf::Color3::OLIVE)); + textureData->add(cvf::Color4ub(cvf::Color3::LIGHT_GRAY)); + textureData->add(cvf::Color4ub(cvf::Color3::BROWN)); + textureData->add(cvf::Color4ub(cvf::Color3::CRIMSON)); + textureData->add(cvf::Color4ub(cvf::Color3::DARK_BLUE)); + textureData->add(cvf::Color4ub(cvf::Color3::DARK_CYAN)); + textureData->add(cvf::Color4ub(cvf::Color3::DARK_GREEN)); + textureData->add(cvf::Color4ub(cvf::Color3::DARK_MAGENTA)); + textureData->add(cvf::Color4ub(cvf::Color3::DARK_ORANGE)); + textureImage->setData(textureData->ptr()->ptr(), 4, 4); + } + + CVF_ASSERT(textureImage->pixel(1, 0) == cvf::Color4ub(cvf::Color3::GREEN)); + CVF_ASSERT(textureImage->pixel(2, 0) == cvf::Color4ub(cvf::Color3::BLUE)); + + return textureImage; + +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref QTBSceneFactory::createTexturedPart(const cvf::OpenGLCapabilities& capabilities) const +{ + cvf::ref geo = createQuadGeoWithTexCoords(cvf::Vec3f(2, 2, 0), cvf::Vec3f(2, 0, 0), cvf::Vec3f(0, 3, 0)); + + cvf::ref textureImage = create4x4ColoredImage(); + + cvf::ref eff = new cvf::Effect; + + if (m_useShaders) + { + cvf::ref texture = new cvf::Texture(textureImage.p()); + + cvf::ref sampler = new cvf::Sampler; + sampler->setMinFilter(cvf::Sampler::LINEAR); + sampler->setMagFilter(cvf::Sampler::NEAREST); + sampler->setWrapModeS(cvf::Sampler::REPEAT); + sampler->setWrapModeT(cvf::Sampler::REPEAT); + + cvf::ref textureBindings = new cvf::RenderStateTextureBindings; + textureBindings->addBinding(texture.p(), sampler.p(), "u_texture2D"); + + eff->setRenderState(textureBindings.p()); + + cvf::ShaderProgramGenerator spGen("MyTexturedStandardHeadlight", cvf::ShaderSourceProvider::instance()); + spGen.configureStandardHeadlightTexture(); + cvf::ref shaderProg = spGen.generate(); + eff->setShaderProgram(shaderProg.p()); + } + else + { + cvf::ref texture = new cvf::Texture2D_FF(textureImage.p()); + texture->setMinFilter(cvf::Texture2D_FF::LINEAR); + texture->setMagFilter(cvf::Texture2D_FF::NEAREST); + texture->setWrapMode(cvf::Texture2D_FF::REPEAT); + + cvf::ref textureMapping = new cvf::RenderStateTextureMapping_FF(texture.p()); + + eff->setRenderState(textureMapping.p()); + } + + cvf::ref part = new cvf::Part; + part->setName("MyTexturedQuad"); + part->setDrawable(0, geo.p()); + part->setEffect(eff.p()); + + return part; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::ref QTBSceneFactory::createDrawableTextPart(const cvf::OpenGLCapabilities& capabilities) const +{ + static int sl_callCount = 0; + cvf::String textStr = cvf::String("Test text string %1").arg(sl_callCount++); + + cvf::ref drawableText = new cvf::DrawableText; + drawableText->setFont(new cvf::FixedAtlasFont(cvf::FixedAtlasFont::LARGE)); + drawableText->setTextColor(cvf::Color3::RED); + + drawableText->addText(textStr, cvf::Vec3f(2, 2, 0)); + drawableText->setCheckPosVisible(false); + + cvf::ref blending = new cvf::RenderStateBlending; + blending->configureTransparencyBlending(); + + cvf::ref eff = new cvf::Effect; + eff->setRenderState(blending.p()); + + if (m_useShaders) + { + cvf::ShaderProgramGenerator spGen("MyTextShaderProgram", cvf::ShaderSourceProvider::instance()); + spGen.addVertexCode(cvf::ShaderSourceRepository::vs_MinimalTexture); + spGen.addFragmentCode(cvf::ShaderSourceRepository::fs_Text); + cvf::ref shaderProg = spGen.generate(); + shaderProg->disableUniformTrackingForUniform("u_texture2D"); + shaderProg->disableUniformTrackingForUniform("u_color"); + eff->setShaderProgram(shaderProg.p()); + } + + cvf::ref part = new cvf::Part; + part->setDrawable(drawableText.p()); + part->setEffect(eff.p()); + + return part; +} diff --git a/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLContext.h b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBSceneFactory.h similarity index 71% rename from Fwk/VizFwk/LibGuiQt/cvfqtOpenGLContext.h rename to Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBSceneFactory.h index 89dc0bc57b..17706009c8 100644 --- a/Fwk/VizFwk/LibGuiQt/cvfqtOpenGLContext.h +++ b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBSceneFactory.h @@ -34,40 +34,31 @@ // //################################################################################################## - -#pragma once - +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfScene.h" #include "cvfOpenGLContext.h" -class QGLContext; - -namespace cvfqt { - //================================================================================================== // -// Derived OpenGLContext that adapts a Qt QGLContext +// // //================================================================================================== -class OpenGLContext : public cvf::OpenGLContext +class QTBSceneFactory { public: - OpenGLContext(cvf::OpenGLContextGroup* contextGroup, QGLContext* backingQGLContext); - virtual ~OpenGLContext(); - - virtual bool initializeContext(); + QTBSceneFactory(bool useShaders); - virtual void makeCurrent(); - virtual bool isCurrent() const; + cvf::ref createTestScene(const cvf::OpenGLCapabilities& capabilities) const; - static void saveOpenGLState(cvf::OpenGLContext* oglContext); - static void restoreOpenGLState(cvf::OpenGLContext* oglContext); +private: + cvf::ref createTexturedPart(const cvf::OpenGLCapabilities& capabilities) const; + cvf::ref createDrawableTextPart(const cvf::OpenGLCapabilities& capabilities) const; + static cvf::ref createQuadGeoWithTexCoords(const cvf::Vec3f& origin, const cvf::Vec3f& u, const cvf::Vec3f& v); + static cvf::ref create4x4ColoredImage(); private: - QGLContext* m_qtGLContext; - bool m_isCoreOpenGLProfile; // This is a Core OpenGL profile. Implies OpenGL version of 3.2 or more - int m_majorVersion; // OpenGL version as reported by Qt - int m_minorVersion; + bool m_useShaders; }; -} diff --git a/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBVizWidget.cpp b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBVizWidget.cpp new file mode 100644 index 0000000000..7edf1cfc5e --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBVizWidget.cpp @@ -0,0 +1,333 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#include "cvfLibCore.h" +#include "cvfLibRender.h" +#include "cvfLibGeometry.h" +#include "cvfLibViewing.h" + +#include "QTBVizWidget.h" +#include "QTBMainWindow.h" + +#include + + + +//================================================================================================== +// +// +// +//================================================================================================== + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QTBVizWidget::QTBVizWidget(cvf::OpenGLContextGroup* contextGroup, QWidget* parent, QTBMainWindow* mainWindow) +: cvfqt::OpenGLWidget(contextGroup, parent), + m_mainWindow(mainWindow) +{ + cvf::Trace::show("QTBVizWidget[%d]::QTBVizWidget()", instanceNumber()); + + initializeMembers(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::initializeMembers() +{ + m_camera = new cvf::Camera; + + cvf::ref rendering = new cvf::Rendering; + rendering->setCamera(m_camera.p()); + + cvf::ref font = new cvf::FixedAtlasFont(cvf::FixedAtlasFont::STANDARD); + + rendering->addOverlayItem(new cvf::OverlayAxisCross(m_camera.p(), font.p())); + + m_titleOverlayTextBox = new cvf::OverlayTextBox(font.p()); + m_titleOverlayTextBox->setText("N/A"); + m_titleOverlayTextBox->setSizeToFitText(); + m_titleOverlayTextBox->setLayout(cvf::OverlayItem::VERTICAL, cvf::OverlayItem::TOP_LEFT); + rendering->addOverlayItem(m_titleOverlayTextBox.p()); + + m_renderSequence = new cvf::RenderSequence; + m_renderSequence->addRendering(rendering.p()); + + m_trackball = new cvf::ManipulatorTrackball; + m_trackball->setCamera(m_camera.p()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::onWidgetOpenGLReady() +{ + cvf::Trace::show("QTBVizWidget[%d]::onWidgetOpenGLReady()", instanceNumber()); + m_mainWindow->handleVizWidgetIsOpenGLReady(this); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QTBVizWidget::~QTBVizWidget() +{ + cvf::Trace::show("QTBVizWidget[%d]::~QTBVizWidget()", instanceNumber()); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::setViewTitle(cvf::String viewTitle) +{ + if (m_titleOverlayTextBox.isNull()) + { + return; + } + + m_titleOverlayTextBox->setText(viewTitle); + m_titleOverlayTextBox->setSizeToFitText(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::String QTBVizWidget::viewTitle() +{ + if (m_titleOverlayTextBox.isNull()) + { + return cvf::String(); + } + + return m_titleOverlayTextBox->text(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::setViewTitleHighlighted(bool highlighted) +{ + if (m_titleOverlayTextBox.isNull()) + { + return; + } + + const cvf::Color3f clr = highlighted ? cvf::Color3f(1.0f, 0.2f, 0.2f) : cvf::Color3f(0.2f, 0.2f, 1.0f); + m_titleOverlayTextBox->setBackgroundColor(clr); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::setScene(cvf::Scene* scene) +{ + cvf::ref rendering = m_renderSequence->firstRendering(); + CVF_ASSERT(rendering.notNull()); + + rendering->setScene(scene); + + if (scene) + { + cvf::BoundingBox bb = scene->boundingBox(); + if (bb.isValid()) + { + m_camera->fitView(bb, -cvf::Vec3d::Z_AXIS, cvf::Vec3d::Y_AXIS); + m_trackball->setRotationPoint(bb.center()); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::Scene* QTBVizWidget::scene() +{ + cvf::ref rendering = m_renderSequence->firstRendering(); + CVF_ASSERT(rendering.notNull()); + + return rendering->scene(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +cvf::OpenGLContext* QTBVizWidget::cvfOpenGLContext() +{ + return cvfqt::OpenGLWidget::cvfOpenGLContext(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::initializeGL() +{ + cvf::Trace::show("QTBVizWidget[%d]::initializeGL()", instanceNumber()); + + cvfqt::OpenGLWidget::initializeGL(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::resizeGL(int width, int height) +{ + cvf::Trace::show("QTBVizWidget[%d]::resizeGL() w=%d h=%d", instanceNumber(), width, height); + + if (m_camera.notNull()) + { + m_camera->viewport()->set(0, 0, width, height); + m_camera->setProjectionAsPerspective(m_camera->fieldOfViewYDeg(), m_camera->nearPlane(), m_camera->farPlane()); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::paintGL() +{ + const int w = width(); + const int h = height(); + cvf::Trace::show("QTBVizWidget[%d]::paintGL(), w=%d h=%d", instanceNumber(), w, h); + + // According to Qt docs, context should already be current + cvf::OpenGLContext* currentOglContext = cvfOpenGLContext(); + CVF_ASSERT(currentOglContext); + CVF_CHECK_OGL(currentOglContext); + + cvf::OpenGLUtils::pushOpenGLState(currentOglContext); + + if (m_renderSequence.notNull()) + { + m_renderSequence->render(currentOglContext); + } + + cvf::OpenGLUtils::popOpenGLState(currentOglContext); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::mouseMoveEvent(QMouseEvent* event) +{ + if (m_renderSequence.isNull()) return; + + Qt::MouseButtons mouseBn = event->buttons(); +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + const int posX = event->position().toPoint().x(); + const int posY = height() - event->position().toPoint().y(); +#else + const int posX = event->x(); + const int posY = height() - event->y(); +#endif + + cvf::ManipulatorTrackball::NavigationType navType = cvf::ManipulatorTrackball::NONE; + if (mouseBn == Qt::LeftButton) + { + navType = cvf::ManipulatorTrackball::PAN; + } + else if (mouseBn == Qt::RightButton) + { + navType = cvf::ManipulatorTrackball::ROTATE; + } + else if (mouseBn == (Qt::LeftButton | Qt::RightButton) || mouseBn == Qt::MiddleButton) + { + navType = cvf::ManipulatorTrackball::WALK; + } + + if (navType != m_trackball->activeNavigation()) + { + m_trackball->startNavigation(navType, posX, posY); + } + + bool needRedraw = m_trackball->updateNavigation(posX, posY); + if (needRedraw) + { + update(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::mousePressEvent(QMouseEvent* event) +{ + if (m_renderSequence.isNull()) return; + +#if QT_VERSION >= QT_VERSION_CHECK(6,0,0) + const int posX = event->position().toPoint().x(); + const int posY = height() - event->position().toPoint().y(); +#else + const int posX = event->x(); + const int posY = height() - event->y(); +#endif + + if (event->buttons() == Qt::LeftButton && event->modifiers() == Qt::ControlModifier) + { + cvf::Rendering* r = m_renderSequence->firstRendering(); + cvf::ref ris = r->rayIntersectSpecFromWindowCoordinates(posX, posY); + + cvf::HitItemCollection hic; + if (r->rayIntersect(*ris, &hic)) + { + cvf::HitItem* item = hic.firstItem(); + CVF_ASSERT(item && item->part()); + + cvf::Vec3d isect = item->intersectionPoint(); + m_trackball->setRotationPoint(isect); + + cvf::Trace::show("hitting part: '%s' coords: %.3f %.3f %.3f", item->part()->name().toAscii().ptr(), isect.x(), isect.y(), isect.z()); + } + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::mouseReleaseEvent(QMouseEvent* /*event*/) +{ + m_trackball->endNavigation(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void QTBVizWidget::closeEvent(QCloseEvent* event) +{ + cvf::Trace::show("QTBVizWidget[%d]::closeEvent()", instanceNumber()); + + cvfqt::OpenGLWidget::closeEvent(event); +} + diff --git a/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBVizWidget.h b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBVizWidget.h new file mode 100644 index 0000000000..4ef0d3ee00 --- /dev/null +++ b/Fwk/VizFwk/TestApps/Qt/QtTestBenchOpenGLWidget/QTBVizWidget.h @@ -0,0 +1,95 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2011-2013 Ceetron 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#pragma once + +#include "cvfBase.h" +#include "cvfObject.h" +#include "cvfRenderSequence.h" +#include "cvfManipulatorTrackball.h" +#include "cvfScene.h" +#include "cvfOpenGLContextGroup.h" +#include "cvfOverlayTextBox.h" + +#include "cvfqtOpenGLWidget.h" + +#include + +class QTBMainWindow; + + +//================================================================================================== +// +// +// +//================================================================================================== +class QTBVizWidget : public cvfqt::OpenGLWidget +{ + Q_OBJECT + +public: + QTBVizWidget(cvf::OpenGLContextGroup* contextGroup, QWidget* parent, QTBMainWindow* mainWindow); + ~QTBVizWidget(); + + void setViewTitle(cvf::String viewTitle); + cvf::String viewTitle(); + void setViewTitleHighlighted(bool highlighted); + + void setScene(cvf::Scene* scene); + cvf::Scene* scene(); + + cvf::OpenGLContext* cvfOpenGLContext(); + +private: + virtual void initializeGL(); + virtual void resizeGL(int width, int height); + virtual void paintGL(); + virtual void mousePressEvent(QMouseEvent* event); + virtual void mouseMoveEvent(QMouseEvent* event); + virtual void mouseReleaseEvent(QMouseEvent* event); + virtual void closeEvent(QCloseEvent *event); + void initializeMembers(); + virtual void onWidgetOpenGLReady(); + +private: + QPointer m_mainWindow; + cvf::ref m_renderSequence; + cvf::ref m_camera; + cvf::ref m_trackball; + cvf::ref m_titleOverlayTextBox; +}; + + diff --git a/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32OpenGLContext.cpp b/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32OpenGLContext.cpp index 69e999b807..9a8809e8d0 100644 --- a/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32OpenGLContext.cpp +++ b/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32OpenGLContext.cpp @@ -119,7 +119,9 @@ bool Win32OpenGLContext::createHardwareContext(HWND hWnd) m_hDC = hDC; m_hRC = hRC; - if (initializeContext()) + cvf::OpenGLContextGroup* ownerContextGroup = group(); + CVF_ASSERT(ownerContextGroup); + if (ownerContextGroup->initializeContextGroup(this)) { return true; } @@ -136,7 +138,11 @@ bool Win32OpenGLContext::createHardwareContext(HWND hWnd) void Win32OpenGLContext::shutdownContext() { // Clears up resources and removes us from our group - cvf::OpenGLContext::shutdownContext(); + cvf::OpenGLContextGroup* ownerContextGroup = group(); + CVF_ASSERT(ownerContextGroup); + + makeCurrent(); + ownerContextGroup->contextAboutToBeShutdown(this); if (m_hRC) { @@ -165,7 +171,14 @@ void Win32OpenGLContext::makeCurrent() { if (m_hDC && m_hRC) { - wglMakeCurrent(m_hDC, m_hRC); + HGLRC currRCBefore = wglGetCurrentContext(); + if (currRCBefore != m_hRC) + { + wglMakeCurrent(m_hDC, m_hRC); + HGLRC currRCAfter = wglGetCurrentContext(); + CVF_ASSERT(currRCAfter = m_hRC); + CVF_UNUSED(currRCAfter); + } } } @@ -177,7 +190,8 @@ bool Win32OpenGLContext::isCurrent() const { if (m_hDC && m_hRC) { - if (wglGetCurrentContext() == m_hRC) + HGLRC currRC = wglGetCurrentContext(); + if (currRC == m_hRC) { return true; } diff --git a/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32OpenGLContext.h b/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32OpenGLContext.h index 4e73b9fdc7..b6f8fd0b7b 100644 --- a/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32OpenGLContext.h +++ b/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32OpenGLContext.h @@ -52,7 +52,7 @@ class Win32OpenGLContext : public cvf::OpenGLContext ~Win32OpenGLContext(); bool createHardwareContext(HWND hWnd); - virtual void shutdownContext(); + void shutdownContext(); virtual void makeCurrent(); virtual bool isCurrent() const; diff --git a/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32SnippetRunner.cpp b/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32SnippetRunner.cpp index 47bb4fc16f..376e5e9424 100644 --- a/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32SnippetRunner.cpp +++ b/Fwk/VizFwk/TestApps/Win32/Win32SnippetRunner/Win32SnippetRunner.cpp @@ -69,11 +69,11 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCm UNREFERENCED_PARAMETER(lpCmdLine); cvf::ShaderSourceProvider* shaderProvider = cvf::ShaderSourceProvider::instance(); - shaderProvider->setSourceRepository(new cvf::ShaderSourceRepositoryFile("../../../LibRender/glsl/")); - shaderProvider->addFileSearchDirectory("../../../Tests/SnippetsBasis/Shaders/"); + shaderProvider->setSourceRepository(new cvf::ShaderSourceRepositoryFile(CVF_CEEVIZ_ROOT_SOURCE_DIR "/LibRender/glsl/")); + shaderProvider->addFileSearchDirectory(CVF_CEEVIZ_ROOT_SOURCE_DIR "/Tests/SnippetsBasis/Shaders/"); shaderProvider->addFileSearchDirectory("./"); - const cvf::String testDataDir = "../../../Tests/TestData/"; + const cvf::String testDataDir = CVF_CEEVIZ_ROOT_SOURCE_DIR "/Tests/TestData/"; cvfu::SnippetFactory* factoryBasis = new SnippetFactoryBasis; factoryBasis->setTestDataDir(testDataDir); @@ -168,7 +168,8 @@ LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lPar { //ref snippet = SnippetRegistry::instance()->createSnippet("snip::MinimalModel"); //ref snippet = SnippetRegistry::instance()->createSnippet("snip::Highlight"); - ref snippet = SnippetRegistry::instance()->createSnippet("snip::Stencil"); + //ref snippet = SnippetRegistry::instance()->createSnippet("snip::Stencil"); + ref snippet = SnippetRegistry::instance()->createSnippet("snip::TransparentWeightedAverage"); sl_snippetWnd = new Win32SnippetWindow; sl_snippetWnd->create(hWnd, snippet.p()); SetFocus(sl_snippetWnd->windowHandle()); diff --git a/Fwk/VizFwk/Tests/LibCore_UnitTests/TriggerTBBCopy.txt b/Fwk/VizFwk/Tests/LibCore_UnitTests/TriggerTBBCopy.txt deleted file mode 100644 index bf816d39e4..0000000000 --- a/Fwk/VizFwk/Tests/LibCore_UnitTests/TriggerTBBCopy.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Sole purpose of this file is to have custom build rules to trigger copying of TBB DLLs diff --git a/Fwk/VizFwk/Tests/LibCore_UnitTests/cvfBase64-Test.cpp b/Fwk/VizFwk/Tests/LibCore_UnitTests/cvfBase64-Test.cpp index 77faadf70b..c42882c28d 100644 --- a/Fwk/VizFwk/Tests/LibCore_UnitTests/cvfBase64-Test.cpp +++ b/Fwk/VizFwk/Tests/LibCore_UnitTests/cvfBase64-Test.cpp @@ -59,7 +59,7 @@ TEST(Base64Test, EncodeDecode) size_t i; for (i = 0; i < binaryDataSize; i++) { - binaryData.set(i, static_cast(i%256)); + binaryData.set(i, static_cast(i%256)); } // Encode binary data diff --git a/Fwk/VizFwk/Tests/LibCore_UnitTests/cvfQuat-Test.cpp b/Fwk/VizFwk/Tests/LibCore_UnitTests/cvfQuat-Test.cpp index adb7ca9708..be839dfc7c 100644 --- a/Fwk/VizFwk/Tests/LibCore_UnitTests/cvfQuat-Test.cpp +++ b/Fwk/VizFwk/Tests/LibCore_UnitTests/cvfQuat-Test.cpp @@ -875,6 +875,6 @@ AxisAngleQuat AAQ_ARRAY[] = -INSTANTIATE_TEST_CASE_P(ParamInst, QuatTestAxisAngle, ::testing::ValuesIn(AAQ_ARRAY)); +INSTANTIATE_TEST_SUITE_P(ParamInst, QuatTestAxisAngle, ::testing::ValuesIn(AAQ_ARRAY)); diff --git a/Fwk/VizFwk/Tests/LibGeometry_UnitTests/TriggerTBBCopy.txt b/Fwk/VizFwk/Tests/LibGeometry_UnitTests/TriggerTBBCopy.txt deleted file mode 100644 index bf816d39e4..0000000000 --- a/Fwk/VizFwk/Tests/LibGeometry_UnitTests/TriggerTBBCopy.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Sole purpose of this file is to have custom build rules to trigger copying of TBB DLLs diff --git a/Fwk/VizFwk/Tests/LibGuiQt_UnitTests/CMakeLists.txt b/Fwk/VizFwk/Tests/LibGuiQt_UnitTests/CMakeLists.txt index b4c678173d..7900127f4a 100644 --- a/Fwk/VizFwk/Tests/LibGuiQt_UnitTests/CMakeLists.txt +++ b/Fwk/VizFwk/Tests/LibGuiQt_UnitTests/CMakeLists.txt @@ -4,8 +4,10 @@ project(LibGuiQt_UnitTests) find_package(OpenGL) -# Qt -if (CEE_USE_QT5) +if (CEE_USE_QT6) + find_package(Qt6 COMPONENTS REQUIRED Core Gui Widgets OpenGLWidgets) + set(QT_LIBRARIES Qt6::Core Qt6::Gui Qt6::Widgets Qt6::OpenGLWidgets ) +elseif (CEE_USE_QT5) find_package(Qt5 COMPONENTS REQUIRED Core Gui Widgets OpenGL) set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) else() diff --git a/Fwk/VizFwk/Tests/LibGuiQt_UnitTests/TriggerTBBCopy.txt b/Fwk/VizFwk/Tests/LibGuiQt_UnitTests/TriggerTBBCopy.txt deleted file mode 100644 index bf816d39e4..0000000000 --- a/Fwk/VizFwk/Tests/LibGuiQt_UnitTests/TriggerTBBCopy.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Sole purpose of this file is to have custom build rules to trigger copying of TBB DLLs diff --git a/Fwk/VizFwk/Tests/LibIo_UnitTests/TriggerTBBCopy.txt b/Fwk/VizFwk/Tests/LibIo_UnitTests/TriggerTBBCopy.txt deleted file mode 100644 index bf816d39e4..0000000000 --- a/Fwk/VizFwk/Tests/LibIo_UnitTests/TriggerTBBCopy.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Sole purpose of this file is to have custom build rules to trigger copying of TBB DLLs diff --git a/Fwk/VizFwk/Tests/LibRegGrid2D_UnitTests/TriggerTBBCopy.txt b/Fwk/VizFwk/Tests/LibRegGrid2D_UnitTests/TriggerTBBCopy.txt deleted file mode 100644 index bf816d39e4..0000000000 --- a/Fwk/VizFwk/Tests/LibRegGrid2D_UnitTests/TriggerTBBCopy.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Sole purpose of this file is to have custom build rules to trigger copying of TBB DLLs diff --git a/Fwk/VizFwk/Tests/LibRender_UnitTests/TriggerTBBCopy.txt b/Fwk/VizFwk/Tests/LibRender_UnitTests/TriggerTBBCopy.txt deleted file mode 100644 index bf816d39e4..0000000000 --- a/Fwk/VizFwk/Tests/LibRender_UnitTests/TriggerTBBCopy.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Sole purpose of this file is to have custom build rules to trigger copying of TBB DLLs diff --git a/Fwk/VizFwk/Tests/LibRender_UnitTests/cvfOpenGLContextGroup-Test.cpp b/Fwk/VizFwk/Tests/LibRender_UnitTests/cvfOpenGLContextGroup-Test.cpp index 8a9f6206f6..7a840a58ad 100644 --- a/Fwk/VizFwk/Tests/LibRender_UnitTests/cvfOpenGLContextGroup-Test.cpp +++ b/Fwk/VizFwk/Tests/LibRender_UnitTests/cvfOpenGLContextGroup-Test.cpp @@ -91,7 +91,7 @@ TEST(OpenGLContextGroupTest, LifeCycle) EXPECT_EQ(2, ctx2->refCount()); EXPECT_EQ(2, ctx3->refCount()); - ctx1->shutdownContext(); + grp->contextAboutToBeShutdown(ctx1.p()); EXPECT_EQ(1, ctx1->refCount()); EXPECT_TRUE(ctx1->group() == NULL); EXPECT_FALSE(grp->containsContext(ctx1.p())); diff --git a/Fwk/VizFwk/Tests/LibStructGrid_UnitTests/TriggerTBBCopy.txt b/Fwk/VizFwk/Tests/LibStructGrid_UnitTests/TriggerTBBCopy.txt deleted file mode 100644 index bf816d39e4..0000000000 --- a/Fwk/VizFwk/Tests/LibStructGrid_UnitTests/TriggerTBBCopy.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Sole purpose of this file is to have custom build rules to trigger copying of TBB DLLs diff --git a/Fwk/VizFwk/Tests/LibUtilities_UnitTests/LibUtilities_UnitTests.cpp b/Fwk/VizFwk/Tests/LibUtilities_UnitTests/LibUtilities_UnitTests.cpp index 29d5b81245..1821092558 100644 --- a/Fwk/VizFwk/Tests/LibUtilities_UnitTests/LibUtilities_UnitTests.cpp +++ b/Fwk/VizFwk/Tests/LibUtilities_UnitTests/LibUtilities_UnitTests.cpp @@ -38,7 +38,7 @@ #include "cvfBase.h" #include "gtest/gtest.h" -#include "gtest/cvftestUtils.h" + #include @@ -54,7 +54,5 @@ int main(int argc, char **argv) testing::InitGoogleTest(&argc, argv); - cvftest::TestDataDir::initializeInstance(cvftest::TestDataDir::DEFAULT_DEFINE_THEN_VIZ_FRAMEWORK, true); - return RUN_ALL_TESTS(); } diff --git a/Fwk/VizFwk/Tests/LibUtilities_UnitTests/TriggerTBBCopy.txt b/Fwk/VizFwk/Tests/LibUtilities_UnitTests/TriggerTBBCopy.txt deleted file mode 100644 index bf816d39e4..0000000000 --- a/Fwk/VizFwk/Tests/LibUtilities_UnitTests/TriggerTBBCopy.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Sole purpose of this file is to have custom build rules to trigger copying of TBB DLLs diff --git a/Fwk/VizFwk/Tests/LibUtilities_UnitTests/cvfuImageTga-Test.cpp b/Fwk/VizFwk/Tests/LibUtilities_UnitTests/cvfuImageTga-Test.cpp index cf09c6326e..e4a4927142 100644 --- a/Fwk/VizFwk/Tests/LibUtilities_UnitTests/cvfuImageTga-Test.cpp +++ b/Fwk/VizFwk/Tests/LibUtilities_UnitTests/cvfuImageTga-Test.cpp @@ -51,7 +51,7 @@ using namespace cvfu; //-------------------------------------------------------------------------------------------------- TEST(ImageTgaTest, LoadUncompressed24bit) { - String fullFileName = cvftest::TestDataDir::instance()->dataDir() + "TgaTestSuite/UTC24.TGA"; + String fullFileName = cvftest::Utils::getTestDataDir() + "TgaTestSuite/UTC24.TGA"; cvf::Trace::show("FN: %s\n", fullFileName.toAscii().ptr()); ref img = ImageTga::loadImage(fullFileName); ASSERT_TRUE(img.notNull()); @@ -68,7 +68,7 @@ TEST(ImageTgaTest, LoadUncompressed24bit) //-------------------------------------------------------------------------------------------------- TEST(ImageTgaTest, LoadCompressed24bit) { - String fullFileName = cvftest::TestDataDir::instance()->dataDir() + "TgaTestSuite/CTC24.TGA"; + String fullFileName = cvftest::Utils::getTestDataDir() + "TgaTestSuite/CTC24.TGA"; cvf::Trace::show("FN: %s\n", fullFileName.toAscii().ptr()); ref img = ImageTga::loadImage(fullFileName); ASSERT_TRUE(img.notNull()); @@ -85,7 +85,7 @@ TEST(ImageTgaTest, LoadCompressed24bit) //-------------------------------------------------------------------------------------------------- TEST(ImageTgaTest, LoadUncompressed32bit) { - String fullFileName = cvftest::TestDataDir::instance()->dataDir() + "TgaTestSuite/UTC32.TGA"; + String fullFileName = cvftest::Utils::getTestDataDir() + "TgaTestSuite/UTC32.TGA"; ref img = ImageTga::loadImage(fullFileName); ASSERT_TRUE(img.notNull()); @@ -101,7 +101,7 @@ TEST(ImageTgaTest, LoadUncompressed32bit) //-------------------------------------------------------------------------------------------------- TEST(ImageTgaTest, LoadCompressed32bit) { - String fullFileName = cvftest::TestDataDir::instance()->dataDir() + "TgaTestSuite/CTC32.TGA"; + String fullFileName = cvftest::Utils::getTestDataDir() + "TgaTestSuite/CTC32.TGA"; ref img = ImageTga::loadImage(fullFileName); ASSERT_TRUE(img.notNull()); diff --git a/Fwk/VizFwk/Tests/LibViewing_UnitTests/TriggerTBBCopy.txt b/Fwk/VizFwk/Tests/LibViewing_UnitTests/TriggerTBBCopy.txt deleted file mode 100644 index bf816d39e4..0000000000 --- a/Fwk/VizFwk/Tests/LibViewing_UnitTests/TriggerTBBCopy.txt +++ /dev/null @@ -1,2 +0,0 @@ - -Sole purpose of this file is to have custom build rules to trigger copying of TBB DLLs diff --git a/Fwk/VizFwk/Tests/SnippetsBasis/snipDepthPeelingFront.cpp b/Fwk/VizFwk/Tests/SnippetsBasis/snipDepthPeelingFront.cpp index dfa50e11c8..aaf81d3bf4 100644 --- a/Fwk/VizFwk/Tests/SnippetsBasis/snipDepthPeelingFront.cpp +++ b/Fwk/VizFwk/Tests/SnippetsBasis/snipDepthPeelingFront.cpp @@ -461,7 +461,7 @@ void DepthPeelingFront::renderFrontToBackPeeling() // 3. Final Pass // --------------------------------------------------------------------- - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, m_openGLContext->defaultFramebufferObject()); glDrawBuffer(GL_BACK); glDisable(GL_DEPTH_TEST); diff --git a/Fwk/VizFwk/Tests/SnippetsBasis/snipTextDrawing.cpp b/Fwk/VizFwk/Tests/SnippetsBasis/snipTextDrawing.cpp index baf53d4830..7e92b530da 100644 --- a/Fwk/VizFwk/Tests/SnippetsBasis/snipTextDrawing.cpp +++ b/Fwk/VizFwk/Tests/SnippetsBasis/snipTextDrawing.cpp @@ -252,13 +252,13 @@ ref TextDrawing::createTextPart() m_textDrawable->setFont(NULL); m_textDrawable->setTextColor(Color3::RED); -// m_textDrawable->addText(L"Text:", cvf::Vec3f(50, 200, 0)); -// m_textDrawable->addText(L" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ", cvf::Vec3f(50, 170, 0)); -// m_textDrawable->addText(L" abcdefghijklmnopqrstuvwxyzæøå", cvf::Vec3f(50, 140, 0)); -// m_textDrawable->addText(L" 0123456789 0123456789 0123456789", cvf::Vec3f(50, 110, 0)); -// m_textDrawable->addText(L" !\"#¤%&/()=?`^*@£$€{[]}´~¨',;.:+-_<>>addText(L" Unicode1: \x03B1\x03B2\x03B3\x03B4\x03B5", cvf::Vec3f(50, 50, 0)); -// m_textDrawable->addText(L" Unicode2: 不仅是因为这两种语言截然不同", cvf::Vec3f(50, 20, 0)); + m_textDrawable->addText(L"Text:", cvf::Vec3f(50, 200, 0)); + m_textDrawable->addText(L" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ", cvf::Vec3f(50, 170, 0)); + m_textDrawable->addText(L" abcdefghijklmnopqrstuvwxyzæøå", cvf::Vec3f(50, 140, 0)); + m_textDrawable->addText(L" 0123456789 0123456789 0123456789", cvf::Vec3f(50, 110, 0)); + m_textDrawable->addText(L" !\"#¤%&/()=?`^*@£$€{[]}´~¨',;.:+-_<>>addText(L" Unicode1: \x03B1\x03B2\x03B3\x03B4\x03B5", cvf::Vec3f(50, 50, 0)); + m_textDrawable->addText(L" Unicode2: 不仅是因为这两种语言截然不同", cvf::Vec3f(50, 20, 0)); // Set up transparency ref blending = new RenderStateBlending; diff --git a/Fwk/VizFwk/ThirdParty/gtest/cvftestUtils.h b/Fwk/VizFwk/ThirdParty/gtest/cvftestUtils.h index cead690dc6..f3cd3fbd16 100644 --- a/Fwk/VizFwk/ThirdParty/gtest/cvftestUtils.h +++ b/Fwk/VizFwk/ThirdParty/gtest/cvftestUtils.h @@ -2,7 +2,6 @@ namespace cvftest { - //================================================================================================== // // Static helper class for unit tests @@ -11,179 +10,35 @@ namespace cvftest { class Utils { public: - static bool doesEnvironmentVarExist(const char* name) - { - const char* env = testing::internal::posix::GetEnv(name); - return env ? true : false; - } - - static std::string getEnvironmentVar(const char* name) - { - const char* env = testing::internal::posix::GetEnv(name); - if (env) - { - return env; - } - else - { - return std::string(); - } - } - - static std::string getMyExecutablePath() + static cvf::String getTestDataDir() { -#ifdef WIN32 - std::string exe = std::string(testing::internal::GetArgvs()[0]); -#else - std::string dir = std::string(testing::internal::FilePath::GetCurrentDir().ToString()); - std::string exe = dir + std::string("/") + std::string(testing::internal::GetArgvs()[0]); + std::string testPath = ""; +#if defined(CVF_CEEVIZ_ROOT_SOURCE_DIR) + testPath = CVF_CEEVIZ_ROOT_SOURCE_DIR "/Tests/TestData/"; #endif - return exe; - } -}; - - - -//================================================================================================== -// -// Helper for making a test data directory available inside unit tests -// -// The data directories can be specified via the environment variables CVF_UTEST_DATA_DIR and -// CVF_UTEST_EXTRA_DATA_DIR. Expects a the path to contain a trailing slash. -// Linux: export CVF_UTEST_DATA_DIR="../../../Tests/TestData/" -// -// The main data dir may be populated with default values if the environment variable isn't set. -// The DefaultDataDir enum determines which default will be used. -//================================================================================================== -class TestDataDir -{ -public: - // What value to use if the test data dir environment variable isn't set? - enum DefaultDataDir - { - EMPTY_STRING, // Empty string - DEFAULT_DEFINE, // Try and set from the CVF_UTEST_DEFAULT_DATA_DIR define (must of course be defined, typical usage is via CMake) - DEFAULT_DEFINE_THEN_VIZ_FRAMEWORK // First try the define above, then fall back to the default test data directory for VizFramework - }; - -public: - /// Static initialize function that sets up the singleton and initializes - /// the values of the data directories based on value of the specified enum - //-------------------------------------------------------------------------------------------------- - static void initializeInstance(DefaultDataDir defaultDataDir, bool verbose) - { - TestDataDir* theInstance = internalInstance(); - theInstance->initialize(defaultDataDir, verbose); - } - /// Get pointer to singleton intance, must call initializeInstance() before use - //-------------------------------------------------------------------------------------------------- - static const TestDataDir* instance() - { - const TestDataDir* theInstance = internalInstance(); - if (!theInstance->m_isInitialized) + std::string testPathEnv = getEnvironmentVar("CVF_UTEST_DATA_DIR"); + if (testPathEnv.length() > 0) { - // Not sure if it is wise to use the gtest internal macros here, but haven't found another solution yet - GTEST_MESSAGE_("TestDataDir::initializeInstance() must be called first!", ::testing::TestPartResult::kFatalFailure); + testPath = testPathEnv; } - return theInstance; - } - /// Returns the main data directory - //-------------------------------------------------------------------------------------------------- - std::string dataDir() const - { - return m_dataDir; - } - - /// Returns the extra data directory - //-------------------------------------------------------------------------------------------------- - std::string extraDataDir() const - { - return m_extraDataDir; + return testPath; } private: - TestDataDir() - : m_isInitialized(false) - { - } - - // Initializes the data members - void initialize(DefaultDataDir defaultDataDir, bool verbose) - { - std::string valSrcStr = "empty"; - - if (Utils::doesEnvironmentVarExist("CVF_UTEST_DATA_DIR")) + static std::string getEnvironmentVar(const char* name) + { + const char* env = testing::internal::posix::GetEnv(name); + if (env) { - m_dataDir = Utils::getEnvironmentVar("CVF_UTEST_DATA_DIR"); - valSrcStr = "environmentVar"; + return env; } else { - if (defaultDataDir != EMPTY_STRING) - { - m_dataDir = getValueOfDefaultDefine(); - if (!m_dataDir.empty()) - { - valSrcStr = "define"; - } - else if (defaultDataDir == DEFAULT_DEFINE_THEN_VIZ_FRAMEWORK) - { - m_dataDir = getVizFrameworkDefault(); - if (!m_dataDir.empty()) - { - valSrcStr = "vizFramework"; - } - } - } - } - - m_extraDataDir = Utils::getEnvironmentVar("CVF_UTEST_EXTRA_DATA_DIR"); - - if (verbose) - { - printf("\n"); - printf("dataDir : \"%s\" [src=%s]\n", m_dataDir.c_str(), valSrcStr.c_str()); - printf("extraDir: \"%s\"\n", m_extraDataDir.c_str()); + return std::string(); } - - m_isInitialized = true; } - - // Extract value set via compile time define - static std::string getValueOfDefaultDefine() - { - std::string defDataDir; -#ifdef CVF_UTEST_DEFAULT_DATA_DIR - defDataDir = CVF_UTEST_DEFAULT_DATA_DIR; -#endif - return defDataDir; - } - - // Determine VizFramework default based on executable path and our fixed dir structure - static std::string getVizFrameworkDefault() - { - std::string exe = Utils::getMyExecutablePath(); - std::string dataDir; -#ifdef WIN32 - dataDir = exe.substr(0, exe.find("VizFwk\\")) + std::string("VizFwk\\Tests\\TestData\\"); -#else - dataDir = exe.substr(0, exe.find("VizFwk/")) + std::string("VizFwk/Tests/TestData/"); -#endif - return dataDir; - } - - static TestDataDir* internalInstance() - { - static TestDataDir sl_theInstance; - return &sl_theInstance; - } - -private: - bool m_isInitialized; - std::string m_dataDir; // The primary data directory - std::string m_extraDataDir; // Optional extra data dir, settable only via environment variable };