Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/visualization/Qt3D/src/G4Qt3DViewer.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /visualization/Qt3D/src/G4Qt3DViewer.cc (Version 11.3.0) and /visualization/Qt3D/src/G4Qt3DViewer.cc (Version 10.7.p2)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
 26 // John Allison  17th June 2019                    26 // John Allison  17th June 2019
 27                                                    27 
                                                   >>  28 #if defined (G4VIS_BUILD_QT3D_DRIVER) || defined (G4VIS_USE_QT3D)
                                                   >>  29 
 28 #include "G4Qt3DViewer.hh"                         30 #include "G4Qt3DViewer.hh"
 29                                                    31 
 30 #include "G4Qt3DSceneHandler.hh"                   32 #include "G4Qt3DSceneHandler.hh"
 31 #include "G4Qt3DUtils.hh"                          33 #include "G4Qt3DUtils.hh"
 32                                                    34 
 33 #include "G4Scene.hh"                              35 #include "G4Scene.hh"
 34 #include "G4UImanager.hh"                          36 #include "G4UImanager.hh"
 35 #include "G4UIQt.hh"                               37 #include "G4UIQt.hh"
 36 #include "G4SystemOfUnits.hh"                      38 #include "G4SystemOfUnits.hh"
 37                                                    39 
 38 #define G4warn G4cout                          << 
 39                                                << 
 40 G4Qt3DViewer::G4Qt3DViewer                         40 G4Qt3DViewer::G4Qt3DViewer
 41 (G4Qt3DSceneHandler& sceneHandler, const G4Str     41 (G4Qt3DSceneHandler& sceneHandler, const G4String& name)
 42 : G4VViewer(sceneHandler, sceneHandler.Increme     42 : G4VViewer(sceneHandler, sceneHandler.IncrementViewCount(), name)
 43 , fQt3DSceneHandler(sceneHandler)                  43 , fQt3DSceneHandler(sceneHandler)
 44 , fKeyPressed(false)                               44 , fKeyPressed(false)
 45 , fMousePressed(false)                             45 , fMousePressed(false)
 46 , fMousePressedX(0.)                               46 , fMousePressedX(0.)
 47 , fMousePressedY(0.)                               47 , fMousePressedY(0.)
 48 {}                                                 48 {}
 49                                                    49 
 50 void G4Qt3DViewer::Initialise()                    50 void G4Qt3DViewer::Initialise()
 51 {                                                  51 {
 52   setObjectName(fName.c_str());                    52   setObjectName(fName.c_str());
 53                                                    53 
 54   fVP.SetAutoRefresh(true);                        54   fVP.SetAutoRefresh(true);
 55   fDefaultVP.SetAutoRefresh(true);                 55   fDefaultVP.SetAutoRefresh(true);
 56                                                    56 
                                                   >>  57   // Background is white (not figured out how to change it) so...
                                                   >>  58   fVP.SetDefaultColour(G4Colour::Black());
                                                   >>  59   fDefaultVP.SetDefaultColour(G4Colour::Black());
                                                   >>  60 
 57   auto UI = G4UImanager::GetUIpointer();           61   auto UI = G4UImanager::GetUIpointer();
 58   auto uiQt = dynamic_cast<G4UIQt*>(UI->GetG4U     62   auto uiQt = dynamic_cast<G4UIQt*>(UI->GetG4UIWindow());
 59   if (!uiQt) {                                     63   if (!uiQt) {
 60     fViewId = -1;  // This flags an error.         64     fViewId = -1;  // This flags an error.
 61     G4warn << "G4Qt3DViewer::G4Qt3DViewer requ <<  65     G4cerr << "G4Qt3DViewer::G4Qt3DViewer requires G4UIQt"
 62          << G4endl;                                66          << G4endl;
 63     return;                                        67     return;
 64   }                                                68   }
 65   fUIWidget = QWidget::createWindowContainer(t     69   fUIWidget = QWidget::createWindowContainer(this);
 66   uiQt->AddTabWidget(fUIWidget,QString(fName))     70   uiQt->AddTabWidget(fUIWidget,QString(fName));
 67                                                    71 
 68   setRootEntity(fQt3DSceneHandler.fpQt3DScene)     72   setRootEntity(fQt3DSceneHandler.fpQt3DScene);
 69 }                                                  73 }
 70                                                    74 
 71 G4Qt3DViewer::~G4Qt3DViewer()                      75 G4Qt3DViewer::~G4Qt3DViewer()
 72 {                                              <<  76 {}
 73   setRootEntity(nullptr);                      << 
 74 }                                              << 
 75                                                << 
 76 void G4Qt3DViewer::resizeEvent(QResizeEvent*)  << 
 77   SetView();                                   << 
 78 }                                              << 
 79                                                    77 
 80 void G4Qt3DViewer::SetView()                       78 void G4Qt3DViewer::SetView()
 81 {                                                  79 {
 82   // Background colour                         << 
 83   defaultFrameGraph()->setClearColor(G4Qt3DUti << 
 84                                                << 
 85   // Get radius of scene, etc.                     80   // Get radius of scene, etc.
 86   // Note that this procedure properly takes i     81   // Note that this procedure properly takes into account zoom, dolly and pan.
 87   const G4Point3D targetPoint                      82   const G4Point3D targetPoint
 88     = fSceneHandler.GetScene()->GetStandardTar     83     = fSceneHandler.GetScene()->GetStandardTargetPoint()
 89     + fVP.GetCurrentTargetPoint ();                84     + fVP.GetCurrentTargetPoint ();
 90   G4double radius = fSceneHandler.GetScene()->     85   G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
 91   if(radius<=0.) radius = 1.;                      86   if(radius<=0.) radius = 1.;
 92   const G4double cameraDistance = fVP.GetCamer     87   const G4double cameraDistance = fVP.GetCameraDistance (radius);
 93   const G4Point3D cameraPosition =                 88   const G4Point3D cameraPosition =
 94     targetPoint + cameraDistance * fVP.GetView     89     targetPoint + cameraDistance * fVP.GetViewpointDirection().unit();
 95   const GLdouble pnear  = fVP.GetNearDistance      90   const GLdouble pnear  = fVP.GetNearDistance (cameraDistance, radius);
 96   const GLdouble pfar   = fVP.GetFarDistance       91   const GLdouble pfar   = fVP.GetFarDistance  (cameraDistance, pnear, radius);
 97   const GLdouble right  = fVP.GetFrontHalfHeig     92   const GLdouble right  = fVP.GetFrontHalfHeight (pnear, radius);
 98   const GLdouble left   = -right;                  93   const GLdouble left   = -right;
 99   const GLdouble top    = fVP.GetFrontHalfHeig     94   const GLdouble top    = fVP.GetFrontHalfHeight (pnear, radius);
100   const GLdouble bottom = -top;                    95   const GLdouble bottom = -top;
101                                                    96 
102   camera()->setObjectName((fName + " camera").     97   camera()->setObjectName((fName + " camera").c_str());
103   camera()->setViewCenter(G4Qt3DUtils::Convert     98   camera()->setViewCenter(G4Qt3DUtils::ConvertToQVector3D(targetPoint));
104   camera()->setPosition(G4Qt3DUtils::ConvertTo     99   camera()->setPosition(G4Qt3DUtils::ConvertToQVector3D(cameraPosition));
105   camera()->setUpVector(G4Qt3DUtils::ConvertTo    100   camera()->setUpVector(G4Qt3DUtils::ConvertToQVector3D(fVP.GetUpVector()));
106                                                   101 
107 //  auto lightEntity = new Qt3DCore::QEntity(f    102 //  auto lightEntity = new Qt3DCore::QEntity(fQt3DSceneHandler.fpQt3DScene);
108 //  auto directionalLight = new Qt3DRender::QD    103 //  auto directionalLight = new Qt3DRender::QDirectionalLight(lightEntity);
109 ////  directionalLight->setColor("white");        104 ////  directionalLight->setColor("white");
110 ////  directionalLight->setIntensity(1.);         105 ////  directionalLight->setIntensity(1.);
111 //  directionalLight->setWorldDirection(G4Qt3D    106 //  directionalLight->setWorldDirection(G4Qt3DUtils::ConvertToQVector3D(fVP.GetActualLightpointDirection()));
112 //  lightEntity->addComponent(directionalLight    107 //  lightEntity->addComponent(directionalLight);
113                                                   108 
114   const auto& size = fUIWidget->size();           109   const auto& size = fUIWidget->size();
115   G4double w = size.width();                      110   G4double w = size.width();
116   G4double h = size.height();                     111   G4double h = size.height();
117 #ifdef G4QT3DDEBUG                                112 #ifdef G4QT3DDEBUG
118   // Curiously w,h are wrong first time - 640,    113   // Curiously w,h are wrong first time - 640,480 instead of (my Mac) 991,452.
119   G4cout << "W,H: " << w << ',' << h << G4endl    114   G4cout << "W,H: " << w << ',' << h << G4endl;
120 #endif                                            115 #endif
121   const G4double aspectRatio = w/h;               116   const G4double aspectRatio = w/h;
122   if (fVP.GetFieldHalfAngle() == 0.) {            117   if (fVP.GetFieldHalfAngle() == 0.) {
123     camera()->lens()->setOrthographicProjectio    118     camera()->lens()->setOrthographicProjection
124     (left*aspectRatio,right*aspectRatio,bottom    119     (left*aspectRatio,right*aspectRatio,bottom,top,pnear,pfar);
125   } else {                                        120   } else {
126     camera()->lens()->setPerspectiveProjection    121     camera()->lens()->setPerspectiveProjection
127     (2.*fVP.GetFieldHalfAngle()/deg,aspectRati    122     (2.*fVP.GetFieldHalfAngle()/deg,aspectRatio,pnear,pfar);
128   }                                               123   }
129 }                                                 124 }
130                                                   125 
131 void G4Qt3DViewer::ClearView()                    126 void G4Qt3DViewer::ClearView()
132 {}                                                127 {}
133                                                   128 
134 void G4Qt3DViewer::DrawView()                     129 void G4Qt3DViewer::DrawView()
135 {                                                 130 {
136   // First, a view should decide when to re-vi    131   // First, a view should decide when to re-visit the G4 kernel.
137   // Sometimes it might not be necessary, e.g.    132   // Sometimes it might not be necessary, e.g., if the scene is stored
138   // in a graphical database (e.g., OpenGL's d    133   // in a graphical database (e.g., OpenGL's display lists) and only
139   // the viewing angle has changed.  But graph    134   // the viewing angle has changed.  But graphics systems without a
140   // graphical database will always need to vi    135   // graphical database will always need to visit the G4 kernel.
141                                                   136 
142   // The fNeedKernelVisit flag might have been    137   // The fNeedKernelVisit flag might have been set by the user in
143   // /vis/viewer/rebuild, but if not, make dec    138   // /vis/viewer/rebuild, but if not, make decision and set flag only
144   // if necessary...                              139   // if necessary...
145   if (!fNeedKernelVisit) KernelVisitDecision()    140   if (!fNeedKernelVisit) KernelVisitDecision();
146   G4bool kernelVisitWasNeeded = fNeedKernelVis    141   G4bool kernelVisitWasNeeded = fNeedKernelVisit; // Keep (ProcessView resets).
147   fLastVP = fVP;                                  142   fLastVP = fVP;
148                                                   143 
149   ProcessView ();  // Clears store and process    144   ProcessView ();  // Clears store and processes scene only if necessary.
150                                                   145 
151   if (kernelVisitWasNeeded) {                     146   if (kernelVisitWasNeeded) {
152     // We might need to do something if the ke    147     // We might need to do something if the kernel was visited.
153   } else {                                        148   } else {
154   }                                               149   }
155                                                   150 
156   // ...before finally...                         151   // ...before finally...
157   FinishView ();       // Flush streams and/or    152   FinishView ();       // Flush streams and/or swap buffers.
158 }                                                 153 }
159                                                   154 
160 void G4Qt3DViewer::ShowView()                     155 void G4Qt3DViewer::ShowView()
161 {                                                 156 {
162 #if QT_VERSION < 0x060000                      << 157   show();
163   // show() may only be called from master thr << 
164   if (G4Threading::IsMasterThread()) {         << 
165     show();                                    << 
166   }                                            << 
167   // The way Qt seems to work, we don't seem t << 
168   // we'll leave it in - it seems not to have  << 
169 #endif                                         << 
170 }                                                 158 }
171                                                   159 
172 void G4Qt3DViewer::FinishView()                   160 void G4Qt3DViewer::FinishView()
173 {                                                 161 {
174 #if QT_VERSION < 0x060000                      << 162   show();
175   if (G4Threading::IsMasterThread()) {         << 
176     show();                                    << 
177   }                                            << 
178 #endif                                         << 
179 }                                              << 
180                                                << 
181 // Note: the order of calling of MovingToVisSu << 
182 // is undefined. The order of calling is       << 
183 //   DoneWithMasterThread                      << 
184 //   MovingToVisSubThread ) or ( SwitchToVisSu << 
185 //   SwitchToVisSubThread )    ( MovingToVisSu << 
186 //   DoneWithVisSubThread                      << 
187 //   MovingToMasterThread                      << 
188 //   SwitchToMasterThread                      << 
189 // So regarding the move/switch to the vis sub << 
190 // If the viewer wishes to accept drawing from << 
191 // But at this point we are still on the maste << 
192 // not known. So it has to wait - a conditiona << 
193 // and the provision of a pointer to the QThre << 
194 // sub-thread has to wait until the QObjects h << 
195                                                << 
196 namespace {                                    << 
197   QThread* masterQThread = nullptr;            << 
198   QThread* visSubThreadQThread = nullptr;      << 
199                                                << 
200   G4Mutex visSubThreadMutex = G4MUTEX_INITIALI << 
201   G4Condition waitForVisSubThreadInitialized = << 
202   G4bool visSubThreadEstablished = false;      << 
203   G4bool qObjectsSwitched = false;             << 
204 }                                              << 
205                                                << 
206 void G4Qt3DViewer::MovingToVisSubThread()      << 
207 // Still on master thread but vis thread has b << 
208 {                                              << 
209   // Make note of master QThread               << 
210   masterQThread = QThread::currentThread();    << 
211                                                << 
212   // Wait until SwitchToVisSubThread has found << 
213   {                                            << 
214   G4AutoLock lock(&visSubThreadMutex);         << 
215   G4CONDITIONWAITLAMBDA(&waitForVisSubThreadIn << 
216   }                                            << 
217                                                << 
218   // Move relevant stuff to vis sub-thread QTh << 
219   auto p1 = fQt3DSceneHandler.fpQt3DScene->par << 
220   if(p1) {                                     << 
221     auto p2 = p1->parent();                    << 
222     if(p2) {                                   << 
223       p2->moveToThread(visSubThreadQThread);   << 
224     } else {                                   << 
225       p1->moveToThread(visSubThreadQThread);   << 
226     }                                          << 
227   }                                            << 
228                                                << 
229   // Inform sub-thread                         << 
230   G4AutoLock lock(&visSubThreadMutex);         << 
231   qObjectsSwitched = true;                     << 
232   lock.unlock();                               << 
233   G4CONDITIONBROADCAST(&waitForVisSubThreadIni << 
234 }                                                 163 }
235                                                   164 
236 void G4Qt3DViewer::SwitchToVisSubThread()         165 void G4Qt3DViewer::SwitchToVisSubThread()
237 // On vis sub-thread before any drawing        << 
238 {                                              << 
239   // Make note of vis-subthread QThread for Mo << 
240   visSubThreadQThread = QThread::currentThread << 
241                                                << 
242   // Let MovingToVisSubThread know we have the << 
243   {                                            << 
244   G4AutoLock lock(&visSubThreadMutex);         << 
245   visSubThreadEstablished = true;              << 
246   G4CONDITIONBROADCAST(&waitForVisSubThreadIni << 
247   }                                            << 
248                                                << 
249   // Wait until MovingToVisSubThread has moved << 
250   {                                            << 
251   G4AutoLock lock(&visSubThreadMutex);         << 
252   G4CONDITIONWAITLAMBDA(&waitForVisSubThreadIn << 
253   }                                            << 
254 }                                              << 
255                                                << 
256 void G4Qt3DViewer::MovingToMasterThread()      << 
257 // On vis sub-thread just before exit          << 
258 {                                                 166 {
259   // Move relevant stuff to master QThread.    << 167 //  fUIWidget->moveToThread(QThread::currentThread());
260   auto p1 = fQt3DSceneHandler.fpQt3DScene->par << 168 //  moveToThread(QThread::currentThread());
261   if(p1) {                                     << 169 //  fQt3DSceneHandler.fpQt3DScene->moveToThread(QThread::currentThread());
262     auto p2 = p1->parent();                    << 170 //  fQt3DSceneHandler.fpTransientObjects->moveToThread(QThread::currentThread());
263     if(p2) {                                   << 171 #ifdef G4QT3DDEBUG
264       p2->moveToThread(masterQThread);         << 172 //  G4cout
265     } else {                                   << 173 //  << "G4Qt3DViewer::SwitchToVisSubThread: (void*)fQt3DSceneHandler.fpQt3DScene: "
266       p1->moveToThread(masterQThread);         << 174 //  << (void*)fQt3DSceneHandler.fpQt3DScene
267     }                                          << 175 //  << G4endl;
268   }                                            << 176 #endif
269                                                << 
270   // Reset                                     << 
271   visSubThreadQThread = nullptr;               << 
272   qObjectsSwitched = false;                    << 
273 }                                                 177 }
274                                                   178 
275 void G4Qt3DViewer::SwitchToMasterThread()         179 void G4Qt3DViewer::SwitchToMasterThread()
276 // On master thread after vis sub-thread has t << 
277 {                                                 180 {
278   visSubThreadEstablished = false;             << 181 //  fUIWidget->moveToThread(QThread::currentThread());
                                                   >> 182 //  moveToThread(QThread::currentThread());
                                                   >> 183 //  fQt3DSceneHandler.fpQt3DScene->moveToThread(QThread::currentThread());
                                                   >> 184 //  fQt3DSceneHandler.fpTransientObjects->moveToThread(QThread::currentThread());
                                                   >> 185 #ifdef G4QT3DDEBUG
                                                   >> 186 //  G4cout
                                                   >> 187 //  << "G4Qt3DViewer::SwitchToMasterThread: (void*)fQt3DSceneHandler.fpQt3DScene: "
                                                   >> 188 //  << (void*)fQt3DSceneHandler.fpQt3DScene
                                                   >> 189 //  << G4endl;
                                                   >> 190 #endif
                                                   >> 191 
                                                   >> 192 #ifdef G4MULTITHREADED
                                                   >> 193   if (G4Threading::IsMultithreadedApplication()) {
                                                   >> 194     // I have not figured out how to draw during a run. In fact, even attempting
                                                   >> 195     // to fill nodes gives the error "Cannot create children for a parent that
                                                   >> 196     // is in a different thread." So instead draw events from kept events.
                                                   >> 197     //
                                                   >> 198     // Setting fNeedKernelVisit=true causes scene deletion and a complete rebuild,
                                                   >> 199     // including trajectories, hits, etc. from kept events.
                                                   >> 200     //
                                                   >> 201     // Clearly this is a limitation because even if you run 1000 events you only
                                                   >> 202     // get those kept (default 100), and even worse, if end-if-event-action is
                                                   >> 203     // "refresh", you only get one event (the last I think).
                                                   >> 204     //
                                                   >> 205     // Also, strictly, there is no need to rebuid run-duration models (detector),
                                                   >> 206     // but a complete rebuild is the easiest way (already imeplemented).
                                                   >> 207     fNeedKernelVisit = true;
                                                   >> 208     DrawView();  // Draw trajectories, etc., from kept events
                                                   >> 209   }
                                                   >> 210 #endif
279 }                                                 211 }
280                                                   212 
281 void G4Qt3DViewer::KernelVisitDecision () {       213 void G4Qt3DViewer::KernelVisitDecision () {
282                                                   214   
283   // If there's a significant difference with     215   // If there's a significant difference with the last view parameters
284   // of either the scene handler or this viewe    216   // of either the scene handler or this viewer, trigger a rebuild.
285                                                   217 
286   if (CompareForKernelVisit(fLastVP)) {           218   if (CompareForKernelVisit(fLastVP)) {
287     NeedKernelVisit ();  // Sets fNeedKernelVi    219     NeedKernelVisit ();  // Sets fNeedKernelVisit.
288   }                                               220   }
289 }                                                 221 }
290                                                   222 
291 G4bool G4Qt3DViewer::CompareForKernelVisit(G4V << 223 G4bool G4Qt3DViewer::CompareForKernelVisit(G4ViewParameters& lastVP)
292 {                                                 224 {
293   // Typical comparison.  Taken from OpenInven << 225   // Typical comparison.  Taken from OpenGL.
294   if (                                            226   if (
295      (vp.GetDrawingStyle ()    != fVP.GetDrawi << 227       (lastVP.GetDrawingStyle ()    != fVP.GetDrawingStyle ())    ||
296      (vp.GetNumberOfCloudPoints()  != fVP.GetN << 228       (lastVP.GetNumberOfCloudPoints()  != fVP.GetNumberOfCloudPoints())  ||
297      (vp.IsAuxEdgeVisible ()   != fVP.IsAuxEdg << 229       (lastVP.IsAuxEdgeVisible ()   != fVP.IsAuxEdgeVisible ())   ||
298      (vp.IsCulling ()          != fVP.IsCullin << 230       (lastVP.IsCulling ()          != fVP.IsCulling ())          ||
299      (vp.IsCullingInvisible () != fVP.IsCullin << 231       (lastVP.IsCullingInvisible () != fVP.IsCullingInvisible ()) ||
300      (vp.IsDensityCulling ()   != fVP.IsDensit << 232       (lastVP.IsDensityCulling ()   != fVP.IsDensityCulling ())   ||
301      (vp.IsCullingCovered ()   != fVP.IsCullin << 233       (lastVP.IsCullingCovered ()   != fVP.IsCullingCovered ())   ||
302      (vp.GetCBDAlgorithmNumber() !=            << 234       (lastVP.GetCBDAlgorithmNumber() !=
303       fVP.GetCBDAlgorithmNumber())             << 235        fVP.GetCBDAlgorithmNumber())                               ||
304      (vp.IsSection ()          != fVP.IsSectio << 236       (lastVP.IsSection ()          != fVP.IsSection ())          ||
305      (vp.IsCutaway ()          != fVP.IsCutawa << 237       (lastVP.IsCutaway ()          != fVP.IsCutaway ())          ||
306      // This assumes use of generic clipping ( << 238       (lastVP.IsExplode ()          != fVP.IsExplode ())          ||
307      // DCUT, cutaway).  If a decision is made << 239       (lastVP.GetNoOfSides ()       != fVP.GetNoOfSides ())       ||
308      // this will need changing.  See G4OpenGL << 240       (lastVP.GetGlobalMarkerScale()    != fVP.GetGlobalMarkerScale())    ||
309      // G4OpenGLStoredViewer.cc::CompareForKer << 241       (lastVP.GetGlobalLineWidthScale() != fVP.GetGlobalLineWidthScale()) ||
310      // G4OpenGLStoredSceneHander::CreateSecti << 242       (lastVP.IsMarkerNotHidden ()  != fVP.IsMarkerNotHidden ())  ||
311      (vp.IsExplode ()          != fVP.IsExplod << 243       (lastVP.GetDefaultVisAttributes()->GetColour() !=
312      (vp.GetNoOfSides ()       != fVP.GetNoOfS << 244        fVP.GetDefaultVisAttributes()->GetColour())                ||
313      (vp.GetGlobalMarkerScale()    != fVP.GetG << 245       (lastVP.GetDefaultTextVisAttributes()->GetColour() !=
314      (vp.GetGlobalLineWidthScale() != fVP.GetG << 246        fVP.GetDefaultTextVisAttributes()->GetColour())            ||
315      (vp.IsMarkerNotHidden ()  != fVP.IsMarker << 247       (lastVP.GetBackgroundColour ()!= fVP.GetBackgroundColour ())||
316      (vp.GetDefaultVisAttributes()->GetColour( << 248       (lastVP.IsPicking ()          != fVP.IsPicking ())          ||
317       fVP.GetDefaultVisAttributes()->GetColour << 249       (lastVP.GetVisAttributesModifiers() !=
318      (vp.GetDefaultTextVisAttributes()->GetCol << 250        fVP.GetVisAttributesModifiers())
319       fVP.GetDefaultTextVisAttributes()->GetCo << 251       ) {
320      (vp.GetBackgroundColour ()!= fVP.GetBackg << 
321      (vp.IsPicking ()          != fVP.IsPickin << 
322      // Scaling for Open Inventor is done by t << 
323      // needs a kernel visit.  (In this respec << 
324      // OpenGL drivers, where it's done in Set << 
325      (vp.GetScaleFactor ()     != fVP.GetScale << 
326      (vp.GetVisAttributesModifiers() !=        << 
327       fVP.GetVisAttributesModifiers())         << 
328      (vp.IsSpecialMeshRendering() !=           << 
329       fVP.IsSpecialMeshRendering())            << 
330      (vp.GetSpecialMeshRenderingOption() !=    << 
331       fVP.GetSpecialMeshRenderingOption())     << 
332      )                                         << 
333   return true;                                 << 
334                                                << 
335   if (vp.IsDensityCulling () &&                << 
336       (vp.GetVisibleDensity () != fVP.GetVisib << 
337     return true;                                  252     return true;
338                                                << 
339   if (vp.GetCBDAlgorithmNumber() > 0) {        << 
340     if (vp.GetCBDParameters().size() != fVP.Ge << 
341     else if (vp.GetCBDParameters() != fVP.GetC << 
342   }                                               253   }
343                                                   254 
344   if (vp.IsSection () &&                       << 255   if (lastVP.IsDensityCulling () &&
345       (vp.GetSectionPlane () != fVP.GetSection << 256       (lastVP.GetVisibleDensity () != fVP.GetVisibleDensity ()))
346     return true;                                  257     return true;
347                                                   258 
348   if (vp.IsCutaway ()) {                       << 259   if (lastVP.GetCBDAlgorithmNumber() > 0) {
349     if (vp.GetCutawayMode() != fVP.GetCutawayM << 260     if (lastVP.GetCBDParameters().size() != fVP.GetCBDParameters().size()) return true;
350     if (vp.GetCutawayPlanes ().size () !=      << 261     else if (lastVP.GetCBDParameters() != fVP.GetCBDParameters()) return true;
351         fVP.GetCutawayPlanes ().size ()) retur << 
352     for (size_t i = 0; i < vp.GetCutawayPlanes << 
353     if (vp.GetCutawayPlanes()[i] != fVP.GetCut << 
354       return true;                             << 
355   }                                               262   }
356                                                   263 
357   if (vp.IsExplode () &&                       << 264   if (lastVP.IsExplode () &&
358       (vp.GetExplodeFactor () != fVP.GetExplod << 265       (lastVP.GetExplodeFactor () != fVP.GetExplodeFactor ()))
359     return true;                               << 
360                                                << 
361   if (vp.IsSpecialMeshRendering() &&           << 
362       (vp.GetSpecialMeshVolumes() != fVP.GetSp << 
363     return true;                                  266     return true;
364                                                   267 
365   return false;                                   268   return false;
366 }                                                 269 }
367                                                   270 
368 void G4Qt3DViewer::keyPressEvent(QKeyEvent* ev    271 void G4Qt3DViewer::keyPressEvent(QKeyEvent* ev)
369 {                                                 272 {
370   fKeyPressed = true;                             273   fKeyPressed = true;
371   fKey = ev->key();                               274   fKey = ev->key();
372 }                                                 275 }
373                                                   276 
374 void G4Qt3DViewer::keyReleaseEvent(QKeyEvent*     277 void G4Qt3DViewer::keyReleaseEvent(QKeyEvent* /*ev*/)
375 {                                                 278 {
376   fKeyPressed = false;                            279   fKeyPressed = false;
377 }                                                 280 }
378                                                   281 
379 void G4Qt3DViewer::mouseDoubleClickEvent(QMous    282 void G4Qt3DViewer::mouseDoubleClickEvent(QMouseEvent* /*ev*/) {}
380                                                   283 
381 void G4Qt3DViewer::mouseMoveEvent(QMouseEvent*    284 void G4Qt3DViewer::mouseMoveEvent(QMouseEvent* ev)
382 {                                                 285 {
383   // I think we only want these if a mouse but    286   // I think we only want these if a mouse button is pressed.
384   // But they come even when not pressed (on m    287   // But they come even when not pressed (on my MacBook Pro trackpad).
385   // Documentation says:                          288   // Documentation says:
386   /* Mouse move events will occur only when a     289   /* Mouse move events will occur only when a mouse button is pressed down,
387    unless mouse tracking has been enabled with    290    unless mouse tracking has been enabled with QWidget::setMouseTracking().*/
388   // But this is a window not a widget.           291   // But this is a window not a widget.
389   // As a workaround we maintain a flag change    292   // As a workaround we maintain a flag changed by mousePress/ReleaseEvent.
390 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))   << 293 
391   G4double x = ev->x();                           294   G4double x = ev->x();
392   G4double y = ev->y();                           295   G4double y = ev->y();
393 #else                                          << 
394   G4double x = ev->position().x();             << 
395   G4double y = ev->position().y();             << 
396 #endif                                         << 
397   G4double dx = x-fMousePressedX;                 296   G4double dx = x-fMousePressedX;
398   G4double dy = y-fMousePressedY;                 297   G4double dy = y-fMousePressedY;
399   fMousePressedX = x;                             298   fMousePressedX = x;
400   fMousePressedY = y;                             299   fMousePressedY = y;
401                                                   300 
402   if (fMousePressed) {                            301   if (fMousePressed) {
403                                                   302 
404     if (fKeyPressed && fKey == Qt::Key_Shift)     303     if (fKeyPressed && fKey == Qt::Key_Shift) {  // Translation (pan)
405                                                   304 
406       const G4double sceneRadius = fQt3DSceneH    305       const G4double sceneRadius = fQt3DSceneHandler.fpScene->GetExtent().GetExtentRadius();
407       const G4double scale = 300;  // Roughly     306       const G4double scale = 300;  // Roughly pixels per window, empirically chosen
408       const G4double dxScene = dx*sceneRadius/    307       const G4double dxScene = dx*sceneRadius/scale;
409       const G4double dyScene = dy*sceneRadius/    308       const G4double dyScene = dy*sceneRadius/scale;
410       fVP.IncrementPan(-dxScene,dyScene);         309       fVP.IncrementPan(-dxScene,dyScene);
411                                                   310 
412     } else {  // Rotation                         311     } else {  // Rotation
413                                                   312 
414       // Simple ad-hoc algorithms                 313       // Simple ad-hoc algorithms
415       const G4Vector3D& x_prime = fVP.GetViewp    314       const G4Vector3D& x_prime = fVP.GetViewpointDirection().cross(fVP.GetUpVector());
416       const G4Vector3D& y_prime = x_prime.cros    315       const G4Vector3D& y_prime = x_prime.cross(fVP.GetViewpointDirection());
417       const G4double scale = 200;  // Roughly     316       const G4double scale = 200;  // Roughly pixels per window, empirically chosen
418       G4Vector3D newViewpointDirection = fVP.G    317       G4Vector3D newViewpointDirection = fVP.GetViewpointDirection();
419       newViewpointDirection += dx*x_prime/scal    318       newViewpointDirection += dx*x_prime/scale;
420       newViewpointDirection += dy*y_prime/scal    319       newViewpointDirection += dy*y_prime/scale;
421       fVP.SetViewpointDirection(newViewpointDi    320       fVP.SetViewpointDirection(newViewpointDirection.unit());
422                                                   321 
423       if (fVP.GetRotationStyle() == G4ViewPara    322       if (fVP.GetRotationStyle() == G4ViewParameters::freeRotation) {
424         G4Vector3D newUpVector = fVP.GetUpVect    323         G4Vector3D newUpVector = fVP.GetUpVector();
425         newUpVector += dx*x_prime/scale;          324         newUpVector += dx*x_prime/scale;
426         newUpVector += dy*y_prime/scale;          325         newUpVector += dy*y_prime/scale;
427         fVP.SetUpVector(newUpVector.unit());      326         fVP.SetUpVector(newUpVector.unit());
428       }                                           327       }
429     }                                             328     }
430   }                                               329   }
431                                                   330 
432   SetView();                                      331   SetView();
433   DrawView();                                     332   DrawView();
434 }                                                 333 }
435                                                   334 
436 void G4Qt3DViewer::mousePressEvent(QMouseEvent    335 void G4Qt3DViewer::mousePressEvent(QMouseEvent* ev)
437 {                                                 336 {
438   fMousePressed = true;                           337   fMousePressed = true;
439 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))   << 
440   fMousePressedX = ev->x();                       338   fMousePressedX = ev->x();
441   fMousePressedY = ev->y();                       339   fMousePressedY = ev->y();
442 #else                                          << 
443   fMousePressedX = ev->position().x();         << 
444   fMousePressedY = ev->position().y();         << 
445 #endif                                         << 
446 }                                                 340 }
447                                                   341 
448 void G4Qt3DViewer::mouseReleaseEvent(QMouseEve    342 void G4Qt3DViewer::mouseReleaseEvent(QMouseEvent* /*ev*/)
449 {                                                 343 {
450   fMousePressed = false;                          344   fMousePressed = false;
451 }                                                 345 }
452                                                   346 
453 void G4Qt3DViewer::wheelEvent(QWheelEvent* ev)    347 void G4Qt3DViewer::wheelEvent(QWheelEvent* ev)
454 {                                                 348 {
455   // Take note of up-down motion only             349   // Take note of up-down motion only
456   const G4double angleY = ev->angleDelta().y()    350   const G4double angleY = ev->angleDelta().y();
457                                                   351 
458   if (fVP.GetFieldHalfAngle() == 0.) {  // Ort    352   if (fVP.GetFieldHalfAngle() == 0.) {  // Orthographic projection
459     const G4double scale = 500;  // Empiricall    353     const G4double scale = 500;  // Empirically chosen
460     fVP.MultiplyZoomFactor(1.+angleY/scale);      354     fVP.MultiplyZoomFactor(1.+angleY/scale);
461   } else {                              // Per    355   } else {                              // Perspective projection
462     const G4double delta = fSceneHandler.GetEx << 356     const G4double scale = fVP.GetFieldHalfAngle()/(10.*deg);  // Empirical
463     fVP.SetDolly(fVP.GetDolly()+angleY*delta); << 357     fVP.SetDolly(fVP.GetDolly()+angleY/scale);
464   }                                               358   }
465                                                   359   
466   SetView();                                      360   SetView();
467   DrawView();                                     361   DrawView();
468 }                                                 362 }
                                                   >> 363 
                                                   >> 364 #endif  // #if defined (G4VIS_BUILD_QT3D_DRIVER) || defined (G4VIS_USE_QT3D)
469                                                   365