diff --git a/CMakeLists.txt b/CMakeLists.txt index d60f236..e931113 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,8 @@ endif() cmake_minimum_required (VERSION 3.26) +set(QT_NO_VERSION_CHECK TRUE) + if(POLICY CMP0167) cmake_policy(SET CMP0167 NEW) endif() @@ -125,18 +127,12 @@ find_package(ROOT CONFIG REQUIRED) include(${ROOT_USE_FILE}) find_package(VTK REQUIRED) -# include(${VTK_USE_FILE}) - -set(GEANT4_USE_HDF5 OFF CACHE BOOL "Use HDF5" FORCE) -find_package(Geant4 REQUIRED) - find_package(pybind11 REQUIRED) - option(CENTOS_SUPPORT "VTK definitions for CentOS" OFF) if(CENTOS_SUPPORT) find_package(VTK CONFIG REQUIRED) - include(${VTK_USE_FILE}) + # include(${VTK_USE_FILE}) else() find_package(VTK REQUIRED COMPONENTS CommonColor @@ -157,7 +153,25 @@ else() RenderingGL2PSOpenGL2 RenderingOpenGL2 RenderingVolumeOpenGL2 - IOGeometry) + IOGeometry + GUISupportQt) +endif() + +find_package(Qt6 COMPONENTS Widgets REQUIRED) + +find_package(Geant4 REQUIRED) +message(STATUS "Geant4 libs: ${Geant4_LIBRARIES}") + +# Sanitize Geant4 targets to remove Qt5 dependencies that conflict with VTK/Qt6 +if(TARGET Geant4::G4interfaces) + set_target_properties(Geant4::G4interfaces PROPERTIES + INTERFACE_LINK_LIBRARIES "Geant4::G4global;Geant4::G4graphics_reps;Geant4::G4intercoms" + ) +endif() +if(TARGET Geant4::G4OpenGL) + set_target_properties(Geant4::G4OpenGL PROPERTIES + INTERFACE_LINK_LIBRARIES "Geant4::G4vis_management;Geant4::G4graphics_reps;Geant4::G4geometry;Geant4::G4materials;Geant4::G4intercoms;Geant4::G4global;OpenGL::GL;OpenGL::GLU" + ) endif() set(CMAKE_REQUIRED_INCLUDES CMAKE_REQUIRED_INCLUDES math.h) diff --git a/app/gcompose/CMakeLists.txt b/app/gcompose/CMakeLists.txt index 7d9ba8e..cfaf492 100644 --- a/app/gcompose/CMakeLists.txt +++ b/app/gcompose/CMakeLists.txt @@ -1,5 +1,15 @@ -add_executable(gcompose src/main.cpp) +add_executable(gcompose + src/main.cpp + src/MainWindow.h + src/MainWindow.cpp +) + +set_target_properties(gcompose PROPERTIES + AUTOMOC ON + AUTOUIC ON + AUTORCC ON +) target_include_directories(gcompose PRIVATE ${SRC_DIR} @@ -8,13 +18,21 @@ target_include_directories(gcompose PRIVATE ${VTK_INCLUDE_DIRS} ) +# Filter Geant4 libraries to remove Qt-dependent ones +set(Geant4_LIBS_FILTERED ${Geant4_LIBRARIES}) +if(Geant4_LIBS_FILTERED) + list(REMOVE_ITEM Geant4_LIBS_FILTERED Geant4::G4interfaces Geant4::G4OpenGL Geant4::G4visQt3D) +endif() + target_link_libraries(gcompose mutomCore mutomMath mutomGeant mutomVtk - ${Geant4_LIBRARIES} + ${Geant4_LIBS_FILTERED} ${VTK_LIBRARIES} + Qt6::Widgets + VTK::GUISupportQt ) install(TARGETS gcompose RUNTIME DESTINATION bin) diff --git a/app/gcompose/src/MainWindow.cpp b/app/gcompose/src/MainWindow.cpp new file mode 100644 index 0000000..10732b6 --- /dev/null +++ b/app/gcompose/src/MainWindow.cpp @@ -0,0 +1,15 @@ +#include "MainWindow.h" +#include + +using namespace uLib; + +MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) { + m_viewport = new Vtk::QViewport(this); + setCentralWidget(m_viewport); + + setWindowTitle("gcompose - Qt VTK Interface"); + resize(1200, 800); +} + +MainWindow::~MainWindow() { +} diff --git a/app/gcompose/src/MainWindow.h b/app/gcompose/src/MainWindow.h new file mode 100644 index 0000000..02dee89 --- /dev/null +++ b/app/gcompose/src/MainWindow.h @@ -0,0 +1,25 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +namespace uLib { +namespace Vtk { +class QViewport; +} +} + +class MainWindow : public QMainWindow { + Q_OBJECT +public: + MainWindow(QWidget* parent = nullptr); + virtual ~MainWindow(); + + uLib::Vtk::QViewport* getViewport() { return m_viewport; } + +private: + uLib::Vtk::QViewport* m_viewport; +}; + +#endif diff --git a/app/gcompose/src/main.cpp b/app/gcompose/src/main.cpp index a6a6185..4bb0e86 100644 --- a/app/gcompose/src/main.cpp +++ b/app/gcompose/src/main.cpp @@ -1,11 +1,13 @@ +#include +#include "MainWindow.h" #include "Math/ContainerBox.h" #include #include "HEP/Detectors/DetectorChamber.h" #include "Vtk/HEP/Detectors/vtkDetectorChamber.h" -#include #include +#include #include #include @@ -14,12 +16,15 @@ #include +#include "Math/Units.h" #include using namespace uLib; +using namespace uLib::literals; int main(int argc, char** argv) { - std::cout << "Starting gcompose application..." << std::endl; + QApplication app(argc, argv); + std::cout << "Starting gcompose Qt application..." << std::endl; ContainerBox world_box(Vector3f(1, 1, 1)); world_box.Scale(Vector3f(20_mm, 20_mm, 20_mm)); @@ -40,29 +45,23 @@ int main(int argc, char** argv) { scene.ConstructWorldBox(&world_box, "G4_AIR"); scene.Initialize(); - // 2. Initialize VTK Viewer - Vtk::Viewer viewer; + // 2. Initialize MainWindow (contains embedded VTK QViewport) + MainWindow window; + Vtk::QViewport* viewport = window.getViewport(); - Vtk::vtkDetectorChamber vtk_d1(&d1); - viewer.AddPuppet(vtk_d1); - - Vtk::vtkDetectorChamber vtk_d2(&d2); - viewer.AddPuppet(vtk_d2); - - Vtk::vtkContainerBox vtk_box(&world_box); - viewer.AddPuppet(vtk_box); + viewport->AddPuppet(vtk_d1); - viewer.GetRenderer()->Render(); + Vtk::vtkDetectorChamber vtk_d2(&d2); + viewport->AddPuppet(vtk_d2); + + Vtk::vtkContainerBox vtk_box(&world_box); + viewport->AddPuppet(vtk_box); + + viewport->ZoomAuto(); std::cout << "Geant4 and VTK scenes are ready." << std::endl; - std::cout << "Starting VTK Interactor..." << std::endl; - - // 3. Start VTK interactor (blocks until window is closed) - viewer.Start(); - - // 4. Clean up - std::cout << "Shutting down..." << std::endl; - - return 0; + + window.show(); + return app.exec(); } diff --git a/src/Core/Debug.h b/src/Core/Debug.h index 7b6e4aa..a495ba3 100644 --- a/src/Core/Debug.h +++ b/src/Core/Debug.h @@ -119,8 +119,8 @@ public: void AddAdapter(AdapterInterface &ad) { m_a.push_back(Adapter(ad)); } void Update() { - foreach(Adapter &ad, m_a) { - foreach(DItem &item, m_v) { + for(Adapter &ad : m_a) { + for(DItem &item : m_v) { item.m_adapter->operator()(ad, item.m_value); } } diff --git a/src/HEP/Geant/CMakeLists.txt b/src/HEP/Geant/CMakeLists.txt index a6801f5..8c8d852 100644 --- a/src/HEP/Geant/CMakeLists.txt +++ b/src/HEP/Geant/CMakeLists.txt @@ -45,7 +45,16 @@ target_link_libraries(${libname} ${PACKAGE_LIBPREFIX}Core ${PACKAGE_LIBPREFIX}Math ${PACKAGE_LIBPREFIX}Detectors - ${Geant4_LIBRARIES} +) + +# Filter Geant4 libraries to remove Qt-dependent ones +set(Geant4_LIBS_FILTERED ${Geant4_LIBRARIES}) +if(Geant4_LIBS_FILTERED) + list(REMOVE_ITEM Geant4_LIBS_FILTERED Geant4::G4interfaces Geant4::G4OpenGL Geant4::G4visQt3D) +endif() + +target_link_libraries(${libname} + ${Geant4_LIBS_FILTERED} ) install(TARGETS ${libname} diff --git a/src/Vtk/CMakeLists.txt b/src/Vtk/CMakeLists.txt index b8bce7c..a8e43f4 100644 --- a/src/Vtk/CMakeLists.txt +++ b/src/Vtk/CMakeLists.txt @@ -2,12 +2,14 @@ set(HEADERS uLibVtkInterface.h uLibVtkViewer.h vtkContainerBox.h vtkHandlerWidget.h + vtkQViewport.h ) set(SOURCES uLibVtkInterface.cxx uLibVtkViewer.cpp vtkContainerBox.cpp vtkHandlerWidget.cpp + vtkQViewport.cpp ) ## Pull in Math VTK wrappers (sets MATH_SOURCES / MATH_HEADERS) @@ -42,9 +44,11 @@ set(ULIB_SELECTED_MODULES ${ULIB_SELECTED_MODULES} Vtk PARENT_SCOPE) add_library(${libname} SHARED ${SOURCES}) set_target_properties(${libname} PROPERTIES - VERSION ${PROJECT_VERSION} - SOVERSION ${PROJECT_SOVERSION}) -target_link_libraries(${libname} ${LIBRARIES}) + SOVERSION ${PROJECT_SOVERSION} + AUTOMOC ON + AUTOUIC ON + AUTORCC ON) +target_link_libraries(${libname} ${LIBRARIES} Qt6::Widgets) install(TARGETS ${libname} EXPORT "uLibTargets" diff --git a/src/Vtk/uLibVtkViewer.cpp b/src/Vtk/uLibVtkViewer.cpp index 24f6ee1..b956c64 100644 --- a/src/Vtk/uLibVtkViewer.cpp +++ b/src/Vtk/uLibVtkViewer.cpp @@ -166,6 +166,8 @@ vtkCornerAnnotation *Viewer::GetAnnotation() { return m_Annotation; } vtkRenderer *Viewer::GetRenderer() { return m_Renderer; } +vtkRenderWindow *Viewer::GetRenderWindow() { return m_RenderWindow; } + vtkRenderWindowInteractor *Viewer::GetInteractor() { return m_RenderWindow->GetInteractor(); } diff --git a/src/Vtk/uLibVtkViewer.h b/src/Vtk/uLibVtkViewer.h index 4185d2b..ff304ec 100644 --- a/src/Vtk/uLibVtkViewer.h +++ b/src/Vtk/uLibVtkViewer.h @@ -76,7 +76,7 @@ public: vtkCornerAnnotation *GetAnnotation(); vtkRenderer *GetRenderer(); - + vtkRenderWindow *GetRenderWindow(); vtkRenderWindowInteractor *GetInteractor(); vtkCameraOrientationWidget *GetCameraWidget(); diff --git a/src/Vtk/vtkQViewport.cpp b/src/Vtk/vtkQViewport.cpp new file mode 100644 index 0000000..0e31bde --- /dev/null +++ b/src/Vtk/vtkQViewport.cpp @@ -0,0 +1,150 @@ +#include "vtkQViewport.h" + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace uLib { +namespace Vtk { + +QViewport::QViewport(QWidget* parent) + : QWidget(parent) + , m_VtkWidget(nullptr) + , m_Renderer(vtkRenderer::New()) + , m_Annotation(vtkCornerAnnotation::New()) + , m_Marker(vtkOrientationMarkerWidget::New()) + , m_CameraWidget(nullptr) +{ + // Build the layout – zero margins so VTK fills the entire widget + auto* layout = new QVBoxLayout(this); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + + m_VtkWidget = new QVTKOpenGLNativeWidget(this); + layout->addWidget(m_VtkWidget); + + // After the Qt widget exists but before the first paint, + // attach the renderer and configure the pipeline. + SetupPipeline(); +} + +QViewport::~QViewport() +{ + m_Renderer->RemoveAllViewProps(); + m_Renderer->Clear(); + + m_Annotation->Delete(); + m_Marker->Delete(); + if (m_CameraWidget) + m_CameraWidget->Delete(); + m_Renderer->Delete(); +} + +void QViewport::SetupPipeline() +{ + // Add our renderer to the QVTKOpenGLNativeWidget's render window + vtkRenderWindow* rw = m_VtkWidget->renderWindow(); + rw->AddRenderer(m_Renderer); + + // Qt will supply its own interactor – grab it + vtkRenderWindowInteractor* iren = rw->GetInteractor(); + + // Trackball-camera interaction style + vtkNew style; + iren->SetInteractorStyle(style); + + // Corner annotation + m_Annotation->GetTextProperty()->SetColor(1, 1, 1); + m_Annotation->GetTextProperty()->SetFontFamilyToArial(); + m_Annotation->GetTextProperty()->SetOpacity(0.5); + m_Annotation->SetMaximumFontSize(10); + m_Annotation->SetText(0, "uLib VTK Viewer - OpenCMT all right reserved."); + m_Renderer->AddViewProp(m_Annotation); + + // Orientation axes marker (bottom-left corner) + vtkNew axes; + m_Marker->SetInteractor(iren); + m_Marker->SetOrientationMarker(axes); + m_Marker->SetViewport(0.0, 0.0, 0.2, 0.2); + m_Marker->SetEnabled(true); + m_Marker->InteractiveOff(); + + // Camera-orientation widget (VTK ≥ 9) +#if VTK_MAJOR_VERSION >= 9 + m_CameraWidget = vtkCameraOrientationWidget::New(); + m_CameraWidget->SetParentRenderer(m_Renderer); + m_CameraWidget->SetInteractor(iren); + m_CameraWidget->On(); +#endif + + m_Renderer->SetBackground(0.15, 0.15, 0.15); + m_Renderer->ResetCamera(); +} + +// ── Public API ──────────────────────────────────────────────────────────────── + +void QViewport::Render() +{ + m_VtkWidget->renderWindow()->Render(); +} + +void QViewport::Reset() +{ + ZoomAuto(); + Render(); +} + +void QViewport::ZoomAuto() +{ + m_Renderer->ResetCameraClippingRange(); + m_Renderer->ResetCamera(); +} + +void QViewport::AddPuppet(Puppet& prop) +{ + prop.ConnectRenderer(m_Renderer); + prop.ConnectInteractor(GetInteractor()); + Render(); +} + +void QViewport::RemovePuppet(Puppet& prop) +{ + prop.DisconnectRenderer(m_Renderer); + Render(); +} + +void QViewport::addProp(vtkProp* prop) +{ + m_Renderer->AddActor(prop); + Render(); +} + +void QViewport::RemoveProp(vtkProp* prop) +{ + m_Renderer->RemoveViewProp(prop); + Render(); +} + +void QViewport::AddWidget(vtk3DWidget* /*widget*/) +{ + // vtk3DWidget integration can be added here if needed +} + +vtkRenderWindow* QViewport::GetRenderWindow() +{ + return m_VtkWidget->renderWindow(); +} + +vtkRenderWindowInteractor* QViewport::GetInteractor() +{ + return m_VtkWidget->renderWindow()->GetInteractor(); +} + +} // namespace Vtk +} // namespace uLib diff --git a/src/Vtk/vtkQViewport.h b/src/Vtk/vtkQViewport.h new file mode 100644 index 0000000..62666e1 --- /dev/null +++ b/src/Vtk/vtkQViewport.h @@ -0,0 +1,69 @@ +#ifndef ULIB_VTK_QVIEWPORT_H +#define ULIB_VTK_QVIEWPORT_H + +#include +#include + +#include +#include +#include +#include +#include + +#include "uLibVtkInterface.h" + +class vtkProp; +class vtk3DWidget; +class vtkRenderWindowInteractor; +class vtkCameraOrientationWidget; + +namespace uLib { +namespace Vtk { + +/** + * QViewport is a self-contained Qt widget that embeds a VTK renderer + * directly into the Qt application (no separate VTK window). + * Puppets and actors are added to the embedded renderer. + */ +class QViewport : public QWidget { + Q_OBJECT +public: + explicit QViewport(QWidget* parent = nullptr); + virtual ~QViewport(); + + // Render scene + void Render(); + void Reset(); + void ZoomAuto(); + + // Puppet / prop management + void AddPuppet(Puppet &prop); + void RemovePuppet(Puppet &prop); + void addProp(vtkProp *prop); + void RemoveProp(vtkProp *prop); + + // Widget integration + void AddWidget(vtk3DWidget *widget); + + // Direct access to VTK internals + vtkRenderer* GetRenderer() { return m_Renderer; } + vtkRenderWindow* GetRenderWindow(); + vtkRenderWindowInteractor* GetInteractor(); + vtkCornerAnnotation* GetAnnotation() { return m_Annotation; } + vtkCameraOrientationWidget* GetCameraWidget(){ return m_CameraWidget; } + QVTKOpenGLNativeWidget* GetWidget() { return m_VtkWidget; } + +private: + void SetupPipeline(); + + QVTKOpenGLNativeWidget* m_VtkWidget; + vtkRenderer* m_Renderer; + vtkCornerAnnotation* m_Annotation; + vtkOrientationMarkerWidget* m_Marker; + vtkCameraOrientationWidget* m_CameraWidget; +}; + +} // namespace Vtk +} // namespace uLib + +#endif // ULIB_VTK_QVIEWPORT_H