Geant4-11
G4OpenGLWin32Viewer.cc
Go to the documentation of this file.
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
32#include "G4VViewer.hh"
33#include "G4VSceneHandler.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
48)
49
51{
52 if(!fHDC) return;
53 if(!fHGLRC) return;
54 ::wglMakeCurrent(fHDC,fHGLRC);
56}
57
60)
61
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
76)
77
79{
80}
81
84)
85
87{
88}
89
92)
93
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
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,
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
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)
176{
177}
178
181)
182
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
203 HWND aWindow
204,UINT aMessage
205,WPARAM aWParam
206,LPARAM aLParam
207)
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
350 HDC aHdc
351)
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
405 G4int x
406,G4int y
407)
410{
411 fMousePressed = true;
412 fMousePressedX = x;
413 fMousePressedY = y;
414}
415
418)
421{
422 fMousePressed = false;
423 fMousePressedX = 0;
424 fMousePressedY = 0;
425}
426
429 G4int dx
430,G4int dy
431)
434{
435 const G4double sceneRadius = GetSceneHandler()->GetScene()
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
445 G4int dx
446,G4int dy
447)
450{
451 // Simple ad-hoc algorithms (borrowed from G4Qt3DViewer)
452 const G4Vector3D& x_prime = fVP.GetViewpointDirection()
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
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
471 G4int delta
472)
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
static constexpr double ps
Definition: G4SIunits.hh:157
static constexpr double deg
Definition: G4SIunits.hh:132
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
static char className[]
Definition: G4Win32.cc:36
#define TRUE
Definition: Globals.hh:27
#define FALSE
Definition: Globals.hh:23
unsigned int getWinHeight() const
void ResizeWindow(unsigned int, unsigned int)
unsigned int getWinWidth() const
void SetZoom(G4int)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
virtual void CreateMainWindow()
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
G4OpenGLWin32Viewer(G4OpenGLSceneHandler &scene)
void ShowView()
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
static LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
void SetShift(G4int, G4int)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
void SetView()
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
void SetRotation(G4int, G4int)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
void ReleaseMouse()
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
static G4bool SetWindowPixelFormat(HDC)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
void TrackMouse(G4int, G4int)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
virtual ~G4OpenGLWin32Viewer()
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
void CreateGLWin32Context()
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
void GetWin32Connection()
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//
const G4VisExtent & GetExtent() const
G4Scene * GetScene() const
G4String fName
Definition: G4VViewer.hh:217
G4int fViewId
Definition: G4VViewer.hh:216
G4ViewParameters fVP
Definition: G4VViewer.hh:219
G4VSceneHandler * GetSceneHandler() const
void SetViewpointDirection(const G4Vector3D &viewpointDirection)
G4int GetWindowAbsoluteLocationHintY(G4int) const
unsigned int GetWindowSizeHintX() const
const G4Vector3D & GetViewpointDirection() const
G4double GetFieldHalfAngle() const
void SetDolly(G4double dolly)
G4int GetWindowAbsoluteLocationHintX(G4int) const
void IncrementPan(G4double right, G4double up)
const G4Vector3D & GetUpVector() const
void SetUpVector(const G4Vector3D &upVector)
RotationStyle GetRotationStyle() const
void MultiplyZoomFactor(G4double zoomFactorMultiplier)
unsigned int GetWindowSizeHintY() const
G4double GetDolly() const
G4double GetExtentRadius() const
Definition: G4VisExtent.cc:75
BasicVector3D< T > cross(const BasicVector3D< T > &v) const
BasicVector3D< T > unit() const