Created attachment 502 [details] problem exercise based on B1 g4 example Hello, I'm developing an application based on geant4-10-04-patch-01 and writing dedicated new GUI using Qt5. I'm also thinking to use already great developed UIQt stuff (hence corresponded QtViewer). What I'm fighting with from few days already is the creation of visualization window(->embedded as a tab in UIQt window), which I want be explicitly coded (without using the managers commands). One can think that this is related to the already discussed thread: "Can I embed Geant4 opengl Window into my own GUI program?" from: http://hypernews.slac.stanford.edu/HyperNews/geant4/get/visualization/624.html?inline=-1 However, my issue is more general - how to create g4 visualization objects without using visManager (it should be possible, though this is c++ modular code, right?) There is nice feature of embedded viewer which is being added as a new tab in the UIQt window. -> What I would like to do is to make the whole UIQt window embedded in my GUI Qt main window independently created. I've managed to do so, however the viewer during creation is not calling the UIQt::AddTabWidget(), which of course should happen trough the polymorphic mechanism (being steered by managers). That only may happen when the wrong (of other type) viewer is created. And indeed this is happening - I cannot understand why, and ask you for HELP, please. When I create the new viewer with "/vis/open OGLSQt" the wrong viewer type is being created from the given SceneHandler: [DEBUG]:: SceneHandler name OGLSQt [DEBUG]:: viewer name viewer-0 (OpenGLStoredX) Having so, I'm trying to create the viewer directly by calling the appropriate method from graphicSystem, initialise and set to be current at the level of visManager. Unfortunately, sth is getting wrong at this stage... I've prepared the exercise based on B1 geant4 example. You can find it in attachment. Thank you in advance for help!
The key issue here is how to write correctly the c++ code for the one line of the geant4 .mac for creating the viewer: "/vis/open OGLSQt" --> c++ code ?? Can anybody help me, please?
Created attachment 506 [details] Creating simple Qt viewer based on B1 g4 example and UIQt class The main issue is how to rewrite the UI command: UImanager->ApplyCommand("/vis/open OGLSQt"); with plain c++ code. I didn't manage with attempts that are commented out in a given example.
Hi Bartlomiej First, I'd like to know a little more about your use case. Why, for instance, is the existing Qt UI and viewer not appropriate for your needs? Have you a more general application in mind? Or perhaps an existing one? Could you not simply extend the existing Qt UI? Secondly, if you proceed, I'd like to say right from the beginning that there is a design to be respected. Each graphics system/type has a "factory" (derived from G4VGraphicsSystem). There are two levels of processing - the scene handler, which takes all objects/models in the scene and turns them into suitable primitives in 3D, and a viewer, which renders to the screen from a particular viewpoint, or to a file or whatever. The factory knows how to create a scene handler and viewer. There may be any number of "factories", any number of scene handlers for any given graphics system and any number of viewers for any given scene handler. Here is an example of a "factory": class G4OpenGLStoredQt: public G4OpenGLQt { public: G4OpenGLStoredQt (); G4VSceneHandler* CreateSceneHandler (const G4String& name = ""); G4VViewer* CreateViewer (G4VSceneHandler&, const G4String& name = ""); }; The vis manager (or one of its messengers) invokes these functions via the virtual function mechanism when the user asks "/vis/sceneHandler/create" or "/vis.viewer/create". The vis manager keeps a list of all scenes, scene handlers and viewers. We have not envisaged that the user would call these functions him/herself, but I guess you could look at the messengers for the above commands and reproduce the code in there somehow, but it would frustrate the design whereby the vis manager keeps control, knows whats going on and makes extensive checks. We have attempted to document all this in the Toolkit Developers Guide/Extending Toolkit Functionality/Visualisation. I'll now go back and look at your comments in a little more detail. John
Hi Bartlomiej I've had a quick look at the code in your attachments. It really does look as though you have made great attempts to respect the design and keep the vis manager informed. That's great. A big effort - well done. Phew! [DEBUG]:: SceneHandler name OGLSQt [DEBUG]:: viewer name viewer-0 (OpenGLStoredX) This is curious. It looks like your scene handler pointers and viewer pointers do not match. What messages do you get if you up the verbosity: G4VisManager* visManager = new G4VisExecutive("Confirmations"); or "/vis/verbose Confirmations"? Looking at the code below it seems you are missing something like G4VViewer* pViewer = pSystem->CreateViewer(); visManager->SetCurrentViewer(pViewer); I will await some feedback from you. Cheers and good luck John Code snippet from main of "B1 2": // A graphics system has been found G4VGraphicsSystem* pSystem = gsl [iGS]; visManager->SetCurrentGraphicsSystem(pSystem); //Create scene handler. // visManager->CreateSceneHandler ("OGLSQt"); G4VSceneHandler* pSceneHandler = pSystem ->CreateSceneHandler("OGLSQt"); visManager->SetCurrentSceneHandler(pSceneHandler); // Attach scene. UImanager->ApplyCommand ("/vis/scene/create"); if (visManager -> GetCurrentScene ()) { UImanager->ApplyCommand ("/vis/sceneHandler/attach"); } ////////////////////////////////////////////////////////////////////////////////////// auto session = new B1UIQt(argc, argv, mw); UImanager->ApplyCommand("/vis/open OGLSQt"); // visManager->CreateViewer("test","600"); auto viewer = visManager->GetCurrentViewer();
Dear John, Thank you for detailed introduction. You are right that I'm creating more general application with the geant4 as the simulation engine. In addition, I'm developing GUI in Qt, hence having all the machinery of the visulalization already implemented in geant4 and interfaced with Qt I thought to simply take what I need - the OGLSQt. However, I've faced to the issue I've described. I thought that having the pgraphic system registered in the visManager, calling the visManager->CreateViewer("MyViewer","600"); would do all the job, but it desn't. In fact, I was trying what you seggested, creating and registering the viewer explicitly, using the G4VGraphicsSystem method, like: G4VViewer* pViewer = pSystem->CreateViewer(*pSceneHandler, "MyViewer"); visManager->SetCurrentViewer(pViewer); Unfortunately, the scene handler doesn't see it: G4VisManager::SetCurrentViewer: viewer now MyViewer ERROR: G4VisManager::IsValidView (): the current scene handler "OGLSQt" has no viewers. Do /vis/viewer/create. Afterwards, I've tried with: pSceneHandler->AddViewerToList(pViewer); pSceneHandler->SetCurrentViewer(pViewer); but this alse doesn't help :( It seems that above reagistraion methods doesn't work? Thank you for helping, Bartek
Hi Bartek OK. Great. Having thought about it a bit more, I think my approach would be to write a complete graphics system - factory, scene handler and viewer - that differed from OGLSQt only in that the viewer embeds itself in your UI rather than G4UIQt. You might be able avoid changing the scene handler at all. Then you can use all the the vis system commands in a .mac file or coded with ApplyCommand. So register your factory G4VisManager* visManager = new G4VisExecutive; visManager -> RegisterGraphicsSystem(new MyOpenGLStoredQt); where G4VSceneHandler* MyOpenGLStoredQt::CreateSceneHandler (const G4String& name) { G4VSceneHandler* pScene = new G4OpenGLStoredQtSceneHandler (*this, name); return pScene; } G4VViewer* G4OpenGLStoredQt::CreateViewer (G4VSceneHandler& scene, const G4String& name) { G4VViewer* pView = 0; pView = new MyOpenGLStoredQtViewer ((G4OpenGLStoredSceneHandler&) scene, name); ... MyOpenGLStoredQtViewer would be identical to G4OpenGLStoredQtViewer except it inherits MyOpenGLQtViewer, in which #include "G4UIQt.hh" is replaced by #include "MyUIQt.hh" I'm not familiar with Qt enough to know exactly how the viewer gets embedded in the UI. It sounds like you have already figured that out. Laurent may be able to help. I'm away today but will look in again on Sunday. John
Sorry. That should be G4VSceneHandler* MyOpenGLStoredQt::CreateSceneHandler (const G4String& name) { G4VSceneHandler* pScene = new G4OpenGLStoredQtSceneHandler (*this, name); return pScene; } G4VViewer* MyOpenGLStoredQt::CreateViewer (G4VSceneHandler& scene, const G4String& name) { G4VViewer* pView = 0; pView = new MyOpenGLStoredQtViewer ((G4OpenGLStoredSceneHandler&) scene, name); ...
Hi John, Indeed this would be very suitable solution! Thank for this suggestion. Trying yo implement this idea, I'm also experiencing some difficulties, which are related to the Geant4 compilation flags. Since my new factory inherits from Geant4 interface, like: ------------ class MyOpenGLQtViewer: public QObject, virtual public G4OpenGLViewer ------------ the corresponding modules should be included in G4 compilation (we have many guards in the code depending on the flags). I've set in the cmake comfiguration (among others): ------------ -DG4VIS_USE=ON -DGEANT4_USE_QT=ON -DGEANT4_USE_OPENGL=ON -DGEANT4_USE_OPENGLQT=ON ------------ Should this be enough to compile the code which has the guard called: G4VIS_BUILD_OPENGL_DRIVER ?? I'm worrying about this since I'm getting the following compilation error: --------------- In file included from /usr/worspace/g4examples/B1/src/B1OpenGLQtViewer.cc:36:0: /mnt/hgfs/Centos7G4-win/g4examples/B1/include/B1OpenGLQtViewer.hh:81:72: error: expected class-name before ‘{’ token class B1OpenGLQtViewer: public QObject, virtual public G4OpenGLViewer { --------------- which suggests that the G4OpenGLViewer was not compiled :( This is really weird, since the factory works well for the 'normal' viewers, like '/vis/open OGLSQt' By making a simple test with try of creating the object (even with wrong constructor arguments list), I see: ------------ /usr/worspace/g4examples/B1/exampleB1.cc:62:19: error: ‘G4OpenGLViewer’ does not name a type; did you mean ‘QOpenGLShader’? auto test = new G4OpenGLViewer{}; ^~~~~~~~~~~~~~ QOpenGLShader ------------ So the file G4OpenGLViewer.hh exist and it is included, for sure, the G4OpenGLViewer definition is missing. Is that mean that the guard: G4VIS_BUILD_OPENGL_DRIVER hasn't been set during the Geant4 compilation? Cheers, Bartek
Hi Bartek Mmmm. The CMake system should set the C-pre-processor flag G4VIS_BUILD_OPENGL_DRIVER if you pass -DGEANT4_USE_QT=ON to cmake. I have to say I've never tested this alone (I'll get back to you on this). I usually have -DGEANT4_USE_OPENGL_X11=ON as well, and that certainly does the trick. Looking at the Installation Guide/Building and Installing/Geant4 Build Options/Standard Options, GEANT4_USE_OPENGL as such does not exist, and cmake should tell you so towards the end. One other point: I would make yours a stored viewer. Miss out the intermediate B1OpenGLQtViewer: class B1OpenGLStoredQtViewer: public QObject, virtual public G4OpenGLStoredViewer { and I think there's no need for virtual inheritance (I might be wrong). John
With -DGEANT4_USE_QT=ON alone I get many, many warnings about shadowed variables but it compiles OK and it certainly looks as though the C-pre-processor flag G4VIS_BUILD_OPENGL_DRIVER is set.
Created attachment 510 [details] B1 example with independent viewer implementation
Hi Bartek Wow! Congratualtions. Looks like you have succeeded. I tried building your example (B1 3) but cmake gives me some errors (see below). I'm not an expert here so I can't think how to fix this. Anyway, it looks good. I propose we close this bug report but please feel free to contact use, either directly or via the User Forum. Hope that's OK. Good luck John CMake Error at CMakeLists.txt:34 (find_package): By not providing "FindQt5.cmake" in CMAKE_MODULE_PATH this project has asked CMake to find a package configuration file provided by "Qt5", but CMake did not find one. Could not find a package configuration file provided by "Qt5" with any of the following names: Qt5Config.cmake qt5-config.cmake Add the installation prefix of "Qt5" to CMAKE_PREFIX_PATH or set "Qt5_DIR" to a directory containing one of the above files. If "Qt5" provides a separate development package or SDK, be sure it has been installed.
Hi John, Indeed, I think that the attached version looks complete. Thank you for all the suggestions! Unfortunately, I cannot test it since I'm still experiencing troubles with compile definition, it seems that the definitions related to G4VIS_BUILD_OPENGL_DRIVER are not available for me (eg. when trying to create an object of G4OpenGLStoredViewer). This caused that I cannot develop independent/new viewer factory. I started new thread in module dedicated to cmake: https://bugzilla-geant4.kek.jp/show_bug.cgi?id=2091 Thank you again, bartek
The issues with the definitions are down to the old GNumake way of building vis drivers which compiled everything, using preprocessor symbols to exclude certain features. It's easy to fix this, but, it would mean obsoleting the old GNUmake system and would require a clear definition of the public/private interface/classes of the OpenGL driver(s).