Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/visualization/OpenGL/src/G4OpenGLWin32Viewer.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 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 // 
 26 // G4OpenGLWin32Viewer : Class to provide Windows specific
 27 //                       functionality for OpenGL
 28 //
 29 // 27/06/2003 : G.Barrand : implementation (at last !).
 30 
 31 #include "G4OpenGLWin32Viewer.hh"
 32 #include "G4VViewer.hh"
 33 #include "G4VSceneHandler.hh"
 34 #include "G4OpenGLSceneHandler.hh"
 35 #include "G4Scene.hh"
 36 
 37 #include "G4ios.hh"
 38 #include "G4VisExtent.hh"
 39 #include "G4LogicalVolume.hh"
 40 #include "G4VSolid.hh"
 41 #include "G4Point3D.hh"
 42 #include "G4Normal3D.hh"
 43 
 44 #include "G4SystemOfUnits.hh"
 45 
 46 //////////////////////////////////////////////////////////////////////////////
 47 void G4OpenGLWin32Viewer::SetView (
 48 ) 
 49 //////////////////////////////////////////////////////////////////////////////
 50 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
 51 {
 52   if(!fHDC) return;
 53   if(!fHGLRC) return;
 54   ::wglMakeCurrent(fHDC,fHGLRC);
 55   G4OpenGLViewer::SetView ();  
 56 }
 57 
 58 //////////////////////////////////////////////////////////////////////////////
 59 void G4OpenGLWin32Viewer::ShowView (
 60 ) 
 61 //////////////////////////////////////////////////////////////////////////////
 62 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
 63 {
 64   if(!fHDC) return;
 65   glFlush ();
 66   // Empty the Windows message queue :
 67   MSG event;
 68   while ( ::PeekMessage(&event, NULL, 0, 0, PM_REMOVE) ) {
 69     ::TranslateMessage(&event);
 70     ::DispatchMessage (&event);
 71   }
 72 }
 73 
 74 //////////////////////////////////////////////////////////////////////////////
 75 void G4OpenGLWin32Viewer::GetWin32Connection (
 76 ) 
 77 //////////////////////////////////////////////////////////////////////////////
 78 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
 79 {
 80 }
 81 
 82 //////////////////////////////////////////////////////////////////////////////
 83 void G4OpenGLWin32Viewer::CreateGLWin32Context (
 84 ) 
 85 //////////////////////////////////////////////////////////////////////////////
 86 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
 87 {
 88 }
 89 
 90 //////////////////////////////////////////////////////////////////////////////
 91 void G4OpenGLWin32Viewer::CreateMainWindow (
 92 ) 
 93 //////////////////////////////////////////////////////////////////////////////
 94 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
 95 {
 96   if(fWindow) return; //Done.
 97 
 98   // Bill Gates stuff...
 99   static const char className[] = "G4OpenGLWin32";
100   static G4bool done = false;
101   if(done==false) {
102     WNDCLASS wc;
103     wc.style = CS_HREDRAW | CS_VREDRAW;
104     wc.lpfnWndProc = (WNDPROC)WindowProc;
105     wc.cbClsExtra = 0;
106     wc.cbWndExtra = 0;
107     wc.hInstance = ::GetModuleHandle(NULL);
108     wc.hIcon = LoadIcon  (NULL, IDI_APPLICATION);
109     wc.hCursor = LoadCursor(NULL,IDC_CROSS);
110     wc.hbrBackground = NULL;
111     wc.lpszMenuName = className;
112     wc.lpszClassName = className;
113     ::RegisterClass(&wc);
114     done = true;
115   }  
116   
117   ResizeWindow(fVP.GetWindowSizeHintX(),fVP.GetWindowSizeHintY());
118 
119   G4int x_res=GetSystemMetrics(SM_CXSCREEN);
120   G4int y_res=GetSystemMetrics(SM_CYSCREEN);
121   
122   //FIXME : NOT tested !
123   fWindow = ::CreateWindowEx(0, className,fName.c_str(),
124          WS_OVERLAPPEDWINDOW,
125          //WS_CHILD | WS_VISIBLE,
126                            //        0,0,
127                            fVP.GetWindowAbsoluteLocationHintX(x_res),
128                            fVP.GetWindowAbsoluteLocationHintY(y_res),
129          getWinWidth(), getWinHeight(),
130          NULL, NULL, 
131          ::GetModuleHandle(NULL),
132          NULL);
133   if(!fWindow) return;
134 
135   ::SetWindowLongPtr(fWindow,GWLP_USERDATA,LONG_PTR(this));
136 
137   // initialize OpenGL rendering :
138   fHDC = ::GetDC(fWindow);
139   if( fHDC && (SetWindowPixelFormat(fHDC)==TRUE) ) {
140     fHGLRC = ::wglCreateContext(fHDC);
141   }
142   
143   if(fHDC && fHGLRC) {
144     ::wglMakeCurrent(fHDC,fHGLRC);
145   }
146 
147   //G.Barrand : avoid to indirectly pass in
148   //              WindowProc/[WM_SIZE,WM_PAINT]/This->DrawView()
149   //            from this method. Else we have crash.
150   fInCreateWindow = true;
151 
152   ::SetForegroundWindow(fWindow);
153   ::ShowWindow(fWindow,SW_SHOWDEFAULT);
154   ::UpdateWindow(fWindow);
155   ::DrawMenuBar(fWindow);
156 
157   fInCreateWindow = false;
158 }
159 
160 //////////////////////////////////////////////////////////////////////////////
161 G4OpenGLWin32Viewer::G4OpenGLWin32Viewer (
162  G4OpenGLSceneHandler& scene
163 )
164 :G4VViewer (scene, -1)
165 ,G4OpenGLViewer (scene)
166 ,fMouseHovered(false)
167 ,fMousePressed(false)
168 ,fMousePressedX(0)
169 ,fMousePressedY(0)
170 ,fHDC(0)
171 ,fWindow(0)
172 ,fHGLRC(0)
173 ,fInCreateWindow(false)
174 //////////////////////////////////////////////////////////////////////////////
175 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
176 {
177 }
178 
179 //////////////////////////////////////////////////////////////////////////////
180 G4OpenGLWin32Viewer::~G4OpenGLWin32Viewer (
181 ) 
182 //////////////////////////////////////////////////////////////////////////////
183 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
184 {
185   // This is the end (Jim Morisson).
186   if (fViewId >= 0) {
187     if(wglGetCurrentContext()!=NULL) wglMakeCurrent(NULL,NULL);
188     if(fHGLRC)  {
189       wglDeleteContext(fHGLRC);
190       fHGLRC = NULL;
191     }
192     
193     if(fWindow) {
194       ::SetWindowLongPtr(fWindow,GWLP_USERDATA,LONG(NULL));
195       if(fHDC) ::ReleaseDC(fWindow,fHDC);
196       ::DestroyWindow(fWindow);
197     }
198   }
199 }
200 
201 //////////////////////////////////////////////////////////////////////////////
202 LRESULT CALLBACK G4OpenGLWin32Viewer::WindowProc(
203  HWND aWindow
204 ,UINT aMessage
205 ,WPARAM aWParam
206 ,LPARAM aLParam
207 )
208 //////////////////////////////////////////////////////////////////////////////
209 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
210 {
211   switch (aMessage) {
212     case WM_SIZE: {
213       //FIXME : have to handle WM_RESIZE
214       // Seems to be done (ovidio.pena AT upm.es, 2021/02/23)
215       auto* This = (G4OpenGLWin32Viewer*)
216                    ::GetWindowLongPtr(aWindow, GWLP_USERDATA);
217       if (This) {
218         This->fWinSize_x = (G4int) LOWORD(aLParam);
219         This->fWinSize_y = (G4int) HIWORD(aLParam);
220         if (!This->fInCreateWindow) {
221           This->SetView();
222           glViewport(0, 0, This->fWinSize_x, This->fWinSize_y);
223           This->DrawView();
224         }
225       }
226       return 0;
227     }
228 
229     case WM_PAINT: {
230       PAINTSTRUCT ps;
231       BeginPaint(aWindow, &ps);
232       auto* This = (G4OpenGLWin32Viewer*)
233                    ::GetWindowLongPtr(aWindow, GWLP_USERDATA);
234       if (This) {
235         //FIXME : To have an automatic refresh someone have to redraw here.
236         // Seems to be done (ovidio.pena AT upm.es, 2021/02/23)
237         if(!This->fInCreateWindow) {
238           This->SetView();
239           This->ClearView();
240           This->DrawView();
241         }
242       }
243       EndPaint(aWindow, &ps);
244       return 0;
245     }
246 
247     case WM_LBUTTONDOWN: {
248       auto* This = (G4OpenGLWin32Viewer*)
249                    ::GetWindowLongPtr(aWindow, GWLP_USERDATA);
250       This->TrackMouse(LOWORD(aLParam), HIWORD(aLParam));
251       return 0;
252     }
253 
254     case WM_RBUTTONDOWN: {
255       auto* This = (G4OpenGLWin32Viewer*)
256                    ::GetWindowLongPtr(aWindow, GWLP_USERDATA);
257       This->TrackMouse(LOWORD(aLParam), HIWORD(aLParam));
258       return 0;
259     }
260 
261     case WM_LBUTTONUP: {
262       auto* This = (G4OpenGLWin32Viewer*)
263                    ::GetWindowLongPtr(aWindow, GWLP_USERDATA);
264       This->ReleaseMouse();
265       return 0;
266     }
267 
268     case WM_RBUTTONUP: {
269       auto* This = (G4OpenGLWin32Viewer*)
270                    ::GetWindowLongPtr(aWindow, GWLP_USERDATA);
271       This->ReleaseMouse();
272       return 0;
273     }
274 
275     case WM_MOUSEHOVER: {
276       auto* This = (G4OpenGLWin32Viewer*)
277                    ::GetWindowLongPtr(aWindow, GWLP_USERDATA);
278       This->fMouseHovered = true;
279             return 0;
280     }
281 
282     case WM_MOUSELEAVE: {
283       auto* This = (G4OpenGLWin32Viewer*)
284                    ::GetWindowLongPtr(aWindow, GWLP_USERDATA);
285       This->fMouseHovered = false;
286       return 0;
287     }
288 
289     case WM_MOUSEMOVE: {
290       auto* This = (G4OpenGLWin32Viewer*)
291                    ::GetWindowLongPtr(aWindow, GWLP_USERDATA);
292 
293       if (!This->fMouseHovered) {
294         // mouse hover/leave tracking
295         TRACKMOUSEEVENT tme;
296         tme.cbSize = sizeof(tme);
297         tme.dwFlags = TME_HOVER | TME_LEAVE;
298         tme.hwndTrack = aWindow;
299         tme.dwHoverTime = HOVER_DEFAULT;
300         ::TrackMouseEvent(&tme);
301         This->fMouseHovered = true;
302       }
303 
304       if (This->fMousePressed) {
305         G4int x = (G4int) LOWORD(aLParam);
306         G4int y = (G4int) HIWORD(aLParam);
307         G4int dx = x - This->fMousePressedX;
308         G4int dy = y - This->fMousePressedY;
309         This->fMousePressedX = x;
310         This->fMousePressedY = y;
311 
312         if (aWParam == MK_LBUTTON) {  // Rotation
313           This->SetRotation(dx, dy);
314         }
315 
316         if (aWParam == MK_RBUTTON) {  // Shift
317           This->SetShift(dx, dy);
318         }
319 
320         This->SetView();
321         This->ClearView();
322         This->DrawView();
323       }
324 
325       return 0;
326     }
327 
328     case WM_MOUSEWHEEL: {
329       auto* This = (G4OpenGLWin32Viewer*)
330                    ::GetWindowLongPtr(aWindow, GWLP_USERDATA);
331 
332       G4int delta = (short) HIWORD(aWParam);
333 
334       This->SetZoom(delta);
335 
336       This->SetView();
337       This->ClearView();
338       This->DrawView();
339       return 0;
340     }
341 
342     default:
343       return DefWindowProc(aWindow, aMessage, aWParam, aLParam);
344   }
345 //  return DefWindowProc(aWindow,aMessage,aWParam,aLParam);
346 }
347 
348 //////////////////////////////////////////////////////////////////////////////
349 G4bool G4OpenGLWin32Viewer::SetWindowPixelFormat(
350  HDC aHdc
351 )
352 //////////////////////////////////////////////////////////////////////////////
353 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
354 {
355   // The ungessable...
356 
357   PIXELFORMATDESCRIPTOR pfd;
358   pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
359   pfd.nVersion = 1;
360   pfd.dwFlags = 
361     PFD_DRAW_TO_WINDOW | 
362     PFD_SUPPORT_OPENGL | 
363     PFD_DOUBLEBUFFER | 
364     PFD_STEREO_DONTCARE;  
365   pfd.iPixelType = PFD_TYPE_RGBA;
366   pfd.cColorBits = 32;
367   pfd.cRedBits = 8;
368   pfd.cRedShift = 16;
369   pfd.cGreenBits = 8;
370   pfd.cGreenShift = 8;
371   pfd.cBlueBits = 8;
372   pfd.cBlueShift = 0;
373   pfd.cAlphaBits = 0;
374   pfd.cAlphaShift = 0;
375   pfd.cAccumBits = 64;  
376   pfd.cAccumRedBits = 16;
377   pfd.cAccumGreenBits = 16;
378   pfd.cAccumBlueBits = 16;
379   pfd.cAccumAlphaBits = 0;
380   pfd.cDepthBits = 32;
381   pfd.cStencilBits = 8;
382   pfd.cAuxBuffers = 0;
383   pfd.iLayerType = PFD_MAIN_PLANE;
384   pfd.bReserved = 0;
385   pfd.dwLayerMask = 0;
386   pfd.dwVisibleMask = 0;
387   pfd.dwDamageMask = 0;
388   
389   G4int pixelIndex = ::ChoosePixelFormat(aHdc,&pfd);
390   if (pixelIndex==0) {
391     pixelIndex = 1; 
392     if (::DescribePixelFormat(aHdc, 
393             pixelIndex, 
394             sizeof(PIXELFORMATDESCRIPTOR), 
395             &pfd)==0) {
396       return false;
397     }
398   }
399   if (::SetPixelFormat(aHdc,pixelIndex,&pfd)==FALSE) return false;
400   return true;
401 }
402 
403 //////////////////////////////////////////////////////////////////////////////
404 void G4OpenGLWin32Viewer::TrackMouse(
405  G4int x
406 ,G4int y
407 )
408 //////////////////////////////////////////////////////////////////////////////
409 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
410 {
411   fMousePressed = true;
412   fMousePressedX = x;
413   fMousePressedY = y;
414 }
415 
416 //////////////////////////////////////////////////////////////////////////////
417 void G4OpenGLWin32Viewer::ReleaseMouse(
418 )
419 //////////////////////////////////////////////////////////////////////////////
420 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
421 {
422   fMousePressed = false;
423   fMousePressedX = 0;
424   fMousePressedY = 0;
425 }
426 
427 //////////////////////////////////////////////////////////////////////////////
428 void G4OpenGLWin32Viewer::SetShift(
429  G4int dx
430 ,G4int dy
431 )
432 //////////////////////////////////////////////////////////////////////////////
433 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
434 {
435   const G4double sceneRadius = GetSceneHandler()->GetScene()
436                              ->GetExtent().GetExtentRadius();
437   const G4double scale = 300;  // Roughly pixels per window, empirically chosen
438   const G4double dxScene = dx*sceneRadius/scale;
439   const G4double dyScene = dy*sceneRadius/scale;
440   fVP.IncrementPan(-dxScene,dyScene);
441 }
442 
443 //////////////////////////////////////////////////////////////////////////////
444 void G4OpenGLWin32Viewer::SetRotation(
445  G4int dx
446 ,G4int dy
447 )
448 //////////////////////////////////////////////////////////////////////////////
449 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
450 {
451   // Simple ad-hoc algorithms (borrowed from G4Qt3DViewer)
452   const G4Vector3D& x_prime = fVP.GetViewpointDirection()
453                               .cross(fVP.GetUpVector());
454   const G4Vector3D& y_prime = x_prime.cross(fVP.GetViewpointDirection());
455   const G4double scale = 200;  // Roughly pixels per window, empirically chosen
456   G4Vector3D newViewpointDirection = fVP.GetViewpointDirection();
457   newViewpointDirection += dx*x_prime/scale;
458   newViewpointDirection += dy*y_prime/scale;
459   fVP.SetViewpointDirection(newViewpointDirection.unit());
460 
461   if (fVP.GetRotationStyle() == G4ViewParameters::freeRotation) {
462       G4Vector3D newUpVector = fVP.GetUpVector();
463       newUpVector += dx*x_prime/scale;
464       newUpVector += dy*y_prime/scale;
465       fVP.SetUpVector(newUpVector.unit());
466   }
467 }
468 
469 //////////////////////////////////////////////////////////////////////////////
470 void G4OpenGLWin32Viewer::SetZoom(
471  G4int delta
472 )
473 //////////////////////////////////////////////////////////////////////////////
474 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
475 {
476     if (fVP.GetFieldHalfAngle() == 0.) {  // Orthographic projection
477         const G4double scale = 500;  // Empirically chosen
478         fVP.MultiplyZoomFactor(1. + delta/scale);
479     } else {                              // Perspective projection
480         const G4double scale = fVP.GetFieldHalfAngle()/(10.*deg);  // Empirical
481         fVP.SetDolly(fVP.GetDolly() + delta/scale);
482     }
483 }
484 
485