Geant4  10.03
G4OpenGLSceneHandler.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 //
27 // $Id: G4OpenGLSceneHandler.cc 99503 2016-09-26 07:17:29Z gcosmo $
28 //
29 //
30 // Andrew Walkden 27th March 1996
31 // OpenGL stored scene - creates OpenGL display lists.
32 // OpenGL immediate scene - draws immediately to buffer
33 // (saving space on server).
34 
35 #ifdef G4VIS_BUILD_OPENGL_DRIVER
36 
37 #include "G4OpenGLSceneHandler.hh"
38 #include "G4OpenGLViewer.hh"
39 #include "G4OpenGLTransform3D.hh"
40 #include "G4Point3D.hh"
41 #include "G4Normal3D.hh"
42 #include "G4Transform3D.hh"
43 #include "G4Polyline.hh"
44 #include "G4Polymarker.hh"
45 #include "G4Text.hh"
46 #include "G4Circle.hh"
47 #include "G4Square.hh"
48 #include "G4VMarker.hh"
49 #include "G4Polyhedron.hh"
50 #include "G4VisAttributes.hh"
51 #include "G4PhysicalVolumeModel.hh"
52 #include "G4VPhysicalVolume.hh"
53 #include "G4LogicalVolume.hh"
54 #include "G4VSolid.hh"
55 #include "G4Scene.hh"
56 #include "G4VisExtent.hh"
57 #include "G4AttHolder.hh"
58 #include "G4PhysicalConstants.hh"
59 #include "G4RunManager.hh"
60 #ifdef G4MULTITHREADED
61 #include "G4MTRunManager.hh"
62 #endif
63 #include "G4Run.hh"
64 
65 const GLubyte G4OpenGLSceneHandler::fStippleMaskHashed [128] = {
66  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
67  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
68  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
69  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
70  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
71  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
72  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
73  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
74  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
75  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
76  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
77  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
78  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
79  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
80  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55,
81  0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55
82 };
83 
84 G4OpenGLSceneHandler::G4OpenGLSceneHandler (G4VGraphicsSystem& system,
85  G4int id,
86  const G4String& name):
87 G4VSceneHandler (system, id, name),
88 #ifdef G4OPENGL_VERSION_2
89 fEmulate_GL_QUADS(false),
90 #endif
91 fPickName(0),
92 fThreePassCapable(false),
93 fSecondPassForTransparencyRequested(false),
94 fSecondPassForTransparency(false),
95 fThirdPassForNonHiddenMarkersRequested(false),
96 fThirdPassForNonHiddenMarkers(false),
97 fEdgeFlag(true)
98 {
99 }
100 
101 G4OpenGLSceneHandler::~G4OpenGLSceneHandler ()
102 {
103  ClearStore ();
104 }
105 
106 void G4OpenGLSceneHandler::ClearAndDestroyAtts()
107 {
108  std::map<GLuint, G4AttHolder*>::iterator i;
109  for (i = fPickMap.begin(); i != fPickMap.end(); ++i) delete i->second;
110  fPickMap.clear();
111 }
112 
113 G4int G4OpenGLSceneHandler::fEntitiesFlushInterval = 100;
114 G4OpenGLSceneHandler::FlushAction
115 G4OpenGLSceneHandler::fFlushAction = G4OpenGLSceneHandler::NthEvent;
116 
117 void G4OpenGLSceneHandler::ScaledFlush()
118 {
119  if (fReadyForTransients) {
120 
121  // Drawing transients, e.g., trajectories.
122 
123  switch (fFlushAction) {
124  case endOfEvent:
125  // If "/vis/scene/endOfEventAction refresh", primitives are flushed at
126  // end of event anyway.
127  // But if "/vis/scene/endOfEventAction accumulate", ShowView is not
128  // called until end of run, so we have to watch for a new event.
129  if (fpScene->GetRefreshAtEndOfEvent()) return;
130  else {
131  // Get event from modeling parameters
132  const G4Event* thisEvent = fpModel->GetModelingParameters()->GetEvent();
133  if (!thisEvent) {glFlush(); return;}
134  G4int thisEventID = thisEvent->GetEventID();
135  static G4int lastEventID = 0;
136  if (thisEventID != lastEventID) {
137  glFlush();
138  lastEventID = thisEventID;
139  }
140  }
141  break;
142  case endOfRun:
143  // If "/vis/scene/endOfRunAction refresh", primitives are flushed at
144  // end of run anyway.
145  // If "/vis/scene/endOfRunAction accumulate", ShowView is never called
146  // so we have to watch for a new run.
147  if (fpScene->GetRefreshAtEndOfRun()) return;
148  else {
150 #ifdef G4MULTITHREADED
153  }
154 #endif
155  if (!runMan) {glFlush(); return;}
156  const G4Run* thisRun = runMan->GetCurrentRun();
157  if (!thisRun) {glFlush(); return;}
158  G4int thisRunID = thisRun->GetRunID();
159  static G4int lastRunID = 0;
160  if (thisRunID != lastRunID) {
161  glFlush();
162  lastRunID = thisRunID;
163  }
164  }
165  break;
166  case eachPrimitive:
167  // This is equivalent to numeric with fEntitiesFlushInterval == 1.
168  fEntitiesFlushInterval = 1;
169  // Fall through to NthPrimitive.
170  case NthPrimitive:
171  { // Encapsulate in scope {} brackets to satisfy Windows.
172  static G4int primitivesWaitingToBeFlushed = 0;
173  primitivesWaitingToBeFlushed++;
174  if (primitivesWaitingToBeFlushed < fEntitiesFlushInterval) return;
175  glFlush();
176  primitivesWaitingToBeFlushed = 0;
177  break;
178  }
179  case NthEvent:
180  // If "/vis/scene/endOfEventAction refresh", primitives are flushed at
181  // end of event anyway.
182  if (fpScene->GetRefreshAtEndOfEvent()) return;
183  else {
184  // Get event from modeling parameters
185  const G4Event* thisEvent = fpModel->GetModelingParameters()->GetEvent();
186  G4int thisEventID = thisEvent->GetEventID();
187  static G4int lastEventID = 0;
188  if (thisEventID != lastEventID) {
189  static G4int eventsWaitingToBeFlushed = 0;
190  eventsWaitingToBeFlushed++;
191  if (eventsWaitingToBeFlushed < fEntitiesFlushInterval) return;
192  glFlush();
193  eventsWaitingToBeFlushed = 0;
194  lastEventID = thisEventID;
195  }
196  }
197  break;
198  case never:
199  break;
200  default:
201  break;
202  }
203 
204  }
205 
206  else
207 
208  {
209 
210  // For run duration model drawing (detector drawing):
211  // Immediate mode: a huge speed up is obtained if flushes are scaled.
212  // Stored mode: no discernable difference since drawing is done to the
213  // back buffer and then swapped.
214  // So eachPrimitive and NthPrimitive make sense. But endOfEvent and
215  // endOfRun are treated as "no action", i.e., a flush will only be issued,
216  // as happens anyway, when drawing is complete.
217 
218  switch (fFlushAction) {
219  case endOfEvent:
220  break;
221  case endOfRun:
222  break;
223  case eachPrimitive:
224  // This is equivalent to NthPrimitive with fEntitiesFlushInterval == 1.
225  fEntitiesFlushInterval = 1;
226  // Fall through to NthPrimitive.
227  case NthPrimitive:
228  { // Encapsulate in scope {} brackets to satisfy Windows.
229  static G4int primitivesWaitingToBeFlushed = 0;
230  primitivesWaitingToBeFlushed++;
231  if (primitivesWaitingToBeFlushed < fEntitiesFlushInterval) return;
232  glFlush();
233  primitivesWaitingToBeFlushed = 0;
234  break;
235  }
236  case NthEvent:
237  break;
238  case never:
239  break;
240  default:
241  break;
242  }
243 
244  }
245 }
246 
247 void G4OpenGLSceneHandler::ProcessScene()
248 {
249  fThreePassCapable = true;
250 
252 
253  // Repeat if required...
254  if (fSecondPassForTransparencyRequested) {
255  fSecondPassForTransparency = true;
257  fSecondPassForTransparency = false;
258  fSecondPassForTransparencyRequested = false;
259  }
260 
261  // And again if required...
262  if (fThirdPassForNonHiddenMarkersRequested) {
263  fThirdPassForNonHiddenMarkers = true;
265  fThirdPassForNonHiddenMarkers = false;
266  fThirdPassForNonHiddenMarkersRequested = false;
267  }
268 
269  fThreePassCapable = false;
270 }
271 
272 void G4OpenGLSceneHandler::PreAddSolid
273 (const G4Transform3D& objectTransformation,
274  const G4VisAttributes& visAttribs)
275 {
276  G4VSceneHandler::PreAddSolid (objectTransformation, visAttribs);
277 }
278 
279 void G4OpenGLSceneHandler::BeginPrimitives
280 (const G4Transform3D& objectTransformation)
281 {
282  G4VSceneHandler::BeginPrimitives (objectTransformation);
283 }
284 
285 void G4OpenGLSceneHandler::EndPrimitives ()
286 {
288 }
289 
290 void G4OpenGLSceneHandler::BeginPrimitives2D
291 (const G4Transform3D& objectTransformation)
292 {
293  G4VSceneHandler::BeginPrimitives2D (objectTransformation);
294 }
295 
296 void G4OpenGLSceneHandler::EndPrimitives2D ()
297 {
299 }
300 
301 G4VSolid* G4OpenGLSceneHandler::CreateSectionSolid ()
302 {
304  // If clipping done in G4OpenGLViewer::SetView
305  // return 0;
306 }
307 
308 G4VSolid* G4OpenGLSceneHandler::CreateCutawaySolid ()
309 {
310  // Cutaway done in G4OpenGLViewer::SetView.
311  return 0;
312  // Else
313  // return G4VSceneHandler::CreateCutawaySolid();
314 }
315 
316 void G4OpenGLSceneHandler::AddPrimitive (const G4Polyline& line)
317 {
318  G4int nPoints = line.size ();
319  if (nPoints <= 0) return;
320 
321  // Note: colour and depth test treated in sub-class.
322 
323 #ifndef G4OPENGL_VERSION_2
324  glDisable (GL_LIGHTING);
325 #endif
326 
327  G4double lineWidth = GetLineWidth(fpVisAttribs);
328  // Need access to method in G4OpenGLViewer. static_cast doesn't
329  // work with a virtual base class, so use dynamic_cast. No need to
330  // test the outcome since viewer is guaranteed to be a
331  // G4OpenGLViewer, but test it anyway to keep Coverity happy.
332  G4OpenGLViewer* pGLViewer = dynamic_cast<G4OpenGLViewer*>(fpViewer);
333  if (pGLViewer) pGLViewer->ChangeLineWidth(lineWidth);
334 
335  fEdgeFlag = true;
336 #ifndef G4OPENGL_VERSION_2
337  glBegin (GL_LINE_STRIP);
338  // No ned glEdgeFlag for lines :
339  // Boundary and nonboundary edge flags on vertices are significant only if GL_POLYGON_MODE is set to GL_POINT or GL_LINE. See glPolygonMode.
340 
341  // glEdgeFlag (GL_TRUE);
342  for (G4int iPoint = 0; iPoint < nPoints; iPoint++) {
343  G4double x, y, z;
344  x = line[iPoint].x();
345  y = line[iPoint].y();
346  z = line[iPoint].z();
347  glVertex3d (x, y, z);
348  }
349  glEnd ();
350 #else
351  glBeginVBO(GL_LINE_STRIP);
352 
353  for (G4int iPoint = 0; iPoint < nPoints; iPoint++) {
354  fOglVertex.push_back(line[iPoint].x());
355  fOglVertex.push_back(line[iPoint].y());
356  fOglVertex.push_back(line[iPoint].z());
357  // normal
358  fOglVertex.push_back(0);
359  fOglVertex.push_back(0);
360  fOglVertex.push_back(1);
361  }
362 
363  glEndVBO();
364 #endif
365 }
366 
367 void G4OpenGLSceneHandler::AddPrimitive (const G4Polymarker& polymarker)
368 {
369  if (polymarker.size() == 0) {
370  return;
371  }
372 
373  // Note: colour and depth test treated in sub-class.
374 
375 #ifndef G4OPENGL_VERSION_2
376  glDisable (GL_LIGHTING);
377 #endif
378 
379  MarkerSizeType sizeType;
380  G4double size = GetMarkerSize(polymarker, sizeType);
381 
382  // Need access to method in G4OpenGLViewer. static_cast doesn't
383  // work with a virtual base class, so use dynamic_cast. No need to
384  // test the outcome since viewer is guaranteed to be a
385  // G4OpenGLViewer, but test it anyway to keep Coverity happy.
386  G4OpenGLViewer* pGLViewer = dynamic_cast<G4OpenGLViewer*>(fpViewer);
387  if (!pGLViewer) return;
388 
389  if (sizeType == world) { // Size specified in world coordinates.
390  G4double lineWidth = GetLineWidth(fpVisAttribs);
391  pGLViewer->ChangeLineWidth(lineWidth);
392 
393  G4VMarker::FillStyle style = polymarker.GetFillStyle();
394 
395  // G4bool filled = false; Not actually used - comment out to prevent compiler warnings (JA).
396  static G4bool hashedWarned = false;
397 
398  switch (style) {
399  case G4VMarker::noFill:
400  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
401  glEdgeFlag (GL_TRUE);
402  //filled = false;
403  break;
404  case G4VMarker::hashed:
405  if (!hashedWarned) {
406  G4cout << "Hashed fill style in G4OpenGLSceneHandler."
407  << "\n Not implemented. Using G4VMarker::filled."
408  << G4endl;
409  hashedWarned = true;
410  }
411  // Maybe use
412  //glPolygonStipple (fStippleMaskHashed);
413  // Drop through to filled...
414  case G4VMarker::filled:
415  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
416  //filled = true;
417  break;
418  }
419  }
420 
421  // Draw...
422  if (sizeType == world) { // Size specified in world coordinates.
423 
424  G4int nSides;
425  G4double startPhi;
426  switch (polymarker.GetMarkerType()) {
427  default:
428  case G4Polymarker::dots:
429  size = 1.;
430  // Drop through to circles
432  nSides = GetNoOfSides(fpVisAttribs);
433  startPhi = 0.;
434  break;
436  nSides = 4;
437  startPhi = -pi / 4.;
438  break;
439  }
440 
441  const G4Vector3D& viewpointDirection =
442  fpViewer -> GetViewParameters().GetViewpointDirection();
443  const G4Vector3D& up = fpViewer->GetViewParameters().GetUpVector();
444  const G4double dPhi = twopi / nSides;
445  const G4double radius = size / 2.;
446  G4Vector3D start = radius * (up.cross(viewpointDirection)).unit();
447  G4double phi;
448  G4int i;
449  for (size_t iPoint = 0; iPoint < polymarker.size (); iPoint++) {
450  fEdgeFlag = true;
451 #ifndef G4OPENGL_VERSION_2
452  glBegin (GL_POLYGON);
453  for (i = 0, phi = startPhi; i < nSides; i++, phi += dPhi) {
454  G4Vector3D r = start; r.rotate(phi, viewpointDirection);
455  G4Vector3D p = polymarker[iPoint] + r;
456  glVertex3d (p.x(), p.y(), p.z());
457  }
458  glEnd ();
459 #else
460  glBeginVBO (GL_TRIANGLE_STRIP);
461  for (i = 0, phi = startPhi; i < nSides; i++, phi += dPhi) {
462  G4Vector3D r = start; r.rotate(phi, viewpointDirection);
463  G4Vector3D p = polymarker[iPoint] + r;
464 
465  fOglVertex.push_back(p.x());
466  fOglVertex.push_back(p.y());
467  fOglVertex.push_back(p.z());
468  // normal
469  fOglVertex.push_back(0);
470  fOglVertex.push_back(0);
471  fOglVertex.push_back(1);
472  }
473  glEndVBO ();
474 #endif
475  }
476 
477  } else { // Size specified in screen (window) coordinates.
478 
479  pGLViewer->ChangePointSize(size);
480 
481  //Antialiasing only for circles
482 #ifndef G4OPENGL_VERSION_2
483  switch (polymarker.GetMarkerType()) {
484  default:
485  case G4Polymarker::dots:
487  glEnable (GL_POINT_SMOOTH); break;
489  glDisable (GL_POINT_SMOOTH); break;
490  }
491 #endif
492 #ifndef G4OPENGL_VERSION_2
493  glBegin (GL_POINTS);
494  for (size_t iPoint = 0; iPoint < polymarker.size (); iPoint++) {
495  G4Point3D centre = polymarker[iPoint];
496  glVertex3d(centre.x(),centre.y(),centre.z());
497  }
498  glEnd();
499 #else
500  glBeginVBO(GL_POINTS);
501 
502  for (size_t iPoint = 0; iPoint < polymarker.size (); iPoint++) {
503  fOglVertex.push_back(polymarker[iPoint].x());
504  fOglVertex.push_back(polymarker[iPoint].y());
505  fOglVertex.push_back(polymarker[iPoint].z());
506  fOglVertex.push_back(0);
507  fOglVertex.push_back(0);
508  fOglVertex.push_back(1);
509  }
510  glEndVBO();
511 #endif
512  }
513 }
514 
515 void G4OpenGLSceneHandler::AddPrimitive (const G4Text& text) {
516  // Pass to specific viewer via virtual function DrawText.
517  // FIXME : Not ready for OPENGL2 for the moment
518 #ifdef G4OPENGL_VERSION_2
519  return;
520 #endif
521  G4OpenGLViewer* pGLViewer = dynamic_cast<G4OpenGLViewer*>(fpViewer);
522  if (pGLViewer) pGLViewer->DrawText(text);
523 }
524 
525 void G4OpenGLSceneHandler::AddPrimitive (const G4Circle& circle) {
526  G4Polymarker oneCircle(circle);
527  oneCircle.push_back(circle.GetPosition());
528  oneCircle.SetMarkerType(G4Polymarker::circles);
529  // Call this AddPrimitive to avoid re-doing sub-class code.
530  G4OpenGLSceneHandler::AddPrimitive(oneCircle);
531 }
532 
533 void G4OpenGLSceneHandler::AddPrimitive (const G4Square& square) {
534  G4Polymarker oneSquare(square);
535  oneSquare.push_back(square.GetPosition());
536  oneSquare.SetMarkerType(G4Polymarker::squares);
537  // Call this AddPrimitive to avoid re-doing sub-class code.
538  G4OpenGLSceneHandler::AddPrimitive(oneSquare);
539 }
540 
541 void G4OpenGLSceneHandler::AddPrimitive (const G4Scale& scale)
542 {
544 }
545 
546 //Method for handling G4Polyhedron objects for drawing solids.
547 void G4OpenGLSceneHandler::AddPrimitive (const G4Polyhedron& polyhedron) {
548 
549  // Assume all facets are planar convex quadrilaterals.
550  // Draw each facet individually
551 
552  if (polyhedron.GetNoFacets() == 0) return;
553 
554  // Need access to data in G4OpenGLViewer. static_cast doesn't work
555  // with a virtual base class, so use dynamic_cast.
556  G4OpenGLViewer* pGLViewer = dynamic_cast<G4OpenGLViewer*>(fpViewer);
557  if (!pGLViewer) return;
558 
559  // Get view parameters that the user can force through the vis
560  // attributes, thereby over-riding the current view parameter.
561  G4ViewParameters::DrawingStyle drawing_style = GetDrawingStyle (fpVisAttribs);
562 
563  // Note that in stored mode, because this call gets embedded in a display
564  // list, it is the colour _at the time of_ creation of the display list, so
565  // even if the colour is changed, for example, by interaction with a Qt
566  // window, current_colour does not change.
567  GLfloat* painting_colour;
568  GLfloat current_colour [4];
569  glGetFloatv (GL_CURRENT_COLOR, current_colour);
570 
571  G4bool isTransparent = false;
572  if (current_colour[3] < 1.) { // This object is transparent
573  isTransparent = true;
574  }
575 
576 
577  if (drawing_style == G4ViewParameters::hlr) {
578  // This is the colour used to paint surfaces in hlr mode.
579  GLfloat clear_colour[4];
580  glGetFloatv (GL_COLOR_CLEAR_VALUE, clear_colour);
581  painting_colour = clear_colour;
582  } else { // drawing_style == G4ViewParameters::hlhsr
583  painting_colour = current_colour;
584  }
585 
586  G4double lineWidth = GetLineWidth(fpVisAttribs);
587  pGLViewer->ChangeLineWidth(lineWidth);
588 
589  G4bool isAuxEdgeVisible = GetAuxEdgeVisible (fpVisAttribs);
590 
591  G4bool clipping = pGLViewer->fVP.IsSection() || pGLViewer->fVP.IsCutaway();
592 
593  // Lighting disabled unless otherwise requested
594 #ifndef G4OPENGL_VERSION_2
595  glDisable (GL_LIGHTING);
596 #endif
597 
598  switch (drawing_style) {
600  // Set up as for hidden line removal but paint polygon faces later...
601  case (G4ViewParameters::hlr):
602  glEnable (GL_STENCIL_TEST);
603  // The stencil buffer is cleared in G4OpenGLViewer::ClearView.
604  // The procedure below leaves it clear.
605  glStencilFunc (GL_ALWAYS, 0, 1);
606  glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT);
607  glEnable (GL_DEPTH_TEST);
608  glDepthFunc (GL_LEQUAL);
609  if (isTransparent) {
610  // Transparent...
611  glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
612  glEnable(GL_COLOR_MATERIAL);
613  glDisable (GL_CULL_FACE);
614  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
615  } else {
616  // Opaque...
617  if (clipping) {
618  glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
619  glEnable(GL_COLOR_MATERIAL);
620  glDisable (GL_CULL_FACE);
621  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
622  } else {
623  glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
624  glEnable(GL_COLOR_MATERIAL);
625  glEnable (GL_CULL_FACE);
626  glCullFace (GL_BACK);
627  glPolygonMode (GL_FRONT, GL_LINE);
628  }
629  }
630  break;
631  case (G4ViewParameters::hsr):
632  glEnable (GL_DEPTH_TEST);
633  glDepthFunc (GL_LEQUAL);
634  if (isTransparent) {
635  // Transparent...
636  glDepthMask (GL_FALSE); // Make depth buffer read-only.
637  glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
638 #ifndef G4OPENGL_VERSION_2
639  glEnable(GL_COLOR_MATERIAL);
640 #endif
641  glDisable (GL_CULL_FACE);
642  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
643  } else {
644  // Opaque...
645  glDepthMask (GL_TRUE); // Make depth buffer writable (default).
646  if (clipping) {
647  glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
648  glEnable(GL_COLOR_MATERIAL);
649  glDisable (GL_CULL_FACE);
650  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
651  } else {
652  glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
653 #ifndef G4OPENGL_VERSION_2
654  glEnable(GL_COLOR_MATERIAL);
655 #endif
656  glEnable (GL_CULL_FACE);
657  glCullFace (GL_BACK);
658  glPolygonMode (GL_FRONT, GL_FILL);
659  }
660  }
661 #ifndef G4OPENGL_VERSION_2
662  if (!fProcessing2D) glEnable (GL_LIGHTING);
663 #endif
664  break;
666  default:
667  glEnable (GL_DEPTH_TEST);
668  glDepthFunc (GL_LEQUAL); //??? was GL_ALWAYS
669  glDisable (GL_CULL_FACE);
670  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
671  break;
672  }
673 
674  //Loop through all the facets...
675  fEdgeFlag = true;
676 #ifndef G4OPENGL_VERSION_2
677  glBegin (GL_QUADS);
678  glEdgeFlag (GL_TRUE);
679 #else
680  fEmulate_GL_QUADS = true;
681  glBeginVBO(GL_TRIANGLE_STRIP);
682 #endif
683  G4bool notLastFace;
684  do {
685 
686  //First, find vertices, edgeflags and normals and note "not last facet"...
687  G4Point3D vertex[4];
688  G4int edgeFlag[4];
689  G4Normal3D normals[4];
690  G4int nEdges;
691  notLastFace = polyhedron.GetNextFacet(nEdges, vertex, edgeFlag, normals);
692 
693  //Loop through the four edges of each G4Facet...
694  for(G4int edgeCount = 0; edgeCount < nEdges; ++edgeCount) {
695  // Check to see if edge is visible or not...
696  if (isAuxEdgeVisible) {
697  edgeFlag[edgeCount] = 1;
698  }
699 #ifndef G4OPENGL_VERSION_2
700  if (edgeFlag[edgeCount] > 0) {
701  if (fEdgeFlag != true) {
702  glEdgeFlag (GL_TRUE);
703  fEdgeFlag = true;
704  }
705  } else {
706  if (fEdgeFlag != false) {
707  glEdgeFlag (GL_FALSE);
708  fEdgeFlag = false;
709  }
710  }
711  glNormal3d (normals[edgeCount].x(),
712  normals[edgeCount].y(),
713  normals[edgeCount].z());
714  glVertex3d (vertex[edgeCount].x(),
715  vertex[edgeCount].y(),
716  vertex[edgeCount].z());
717 #else
718 
719  fOglVertex.push_back(vertex[edgeCount].x());
720  fOglVertex.push_back(vertex[edgeCount].y());
721  fOglVertex.push_back(vertex[edgeCount].z());
722 
723  fOglVertex.push_back(normals[edgeCount].x());
724  fOglVertex.push_back(normals[edgeCount].y());
725  fOglVertex.push_back(normals[edgeCount].z());
726 
727 #endif
728 
729  }
730 
731  // HepPolyhedron produces triangles too; in that case add an extra
732  // vertex identical to first...
733  if (nEdges == 3) {
734  G4int edgeCount = 3;
735  normals[edgeCount] = normals[0];
736  vertex[edgeCount] = vertex[0];
737 #ifndef G4OPENGL_VERSION_2
738  edgeFlag[edgeCount] = -1;
739  if (fEdgeFlag != false) {
740  glEdgeFlag (GL_FALSE);
741  fEdgeFlag = false;
742  }
743 
744  glNormal3d (normals[edgeCount].x(),
745  normals[edgeCount].y(),
746  normals[edgeCount].z());
747  glVertex3d (vertex[edgeCount].x(),
748  vertex[edgeCount].y(),
749  vertex[edgeCount].z());
750 #else
751  fOglVertex.push_back(vertex[edgeCount].x());
752  fOglVertex.push_back(vertex[edgeCount].y());
753  fOglVertex.push_back(vertex[edgeCount].z());
754 
755  fOglVertex.push_back(normals[edgeCount].x());
756  fOglVertex.push_back(normals[edgeCount].y());
757  fOglVertex.push_back(normals[edgeCount].z());
758 
759 #endif
760  }
761  // Trap situation where number of edges is > 4...
762  if (nEdges > 4) {
763  G4cerr <<
764  "G4OpenGLSceneHandler::AddPrimitive(G4Polyhedron): WARNING"
765  "\n G4Polyhedron facet with " << nEdges << " edges" << G4endl;
766  }
767 
768 
769  // Do it all over again (twice) for hlr...
770  if (drawing_style == G4ViewParameters::hlr ||
771  drawing_style == G4ViewParameters::hlhsr) {
772 
773 #ifndef G4OPENGL_VERSION_2
774  glDisable(GL_COLOR_MATERIAL); // Revert to glMaterial for hlr/sr.
775 #endif
776 
777 #ifndef G4OPENGL_VERSION_2
778  glEnd (); // Placed here to balance glBegin above, allowing GL
779 #else
780  glEndVBO();
781 #endif
782  // state changes below, then glBegin again. Avoids
783  // having glBegin/End pairs *inside* loop in the more
784  // usual case of no hidden line removal.
785 
786  // Lighting disabled unless otherwise requested
787  glDisable (GL_LIGHTING);
788 
789  // Draw through stencil...
790  glStencilFunc (GL_EQUAL, 0, 1);
791  glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
792  if (drawing_style == G4ViewParameters::hlhsr) {
793  if (!fProcessing2D) glEnable (GL_LIGHTING);
794  }
795  glEnable (GL_DEPTH_TEST);
796  glDepthFunc (GL_LEQUAL);
797  if (isTransparent) {
798  // Transparent...
799  glDepthMask (GL_FALSE); // Make depth buffer read-only.
800  glDisable (GL_CULL_FACE);
801  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
802  } else {
803  // Opaque...
804  glDepthMask (GL_TRUE); // Make depth buffer writable (default).
805  if (clipping) {
806  glDisable (GL_CULL_FACE);
807  glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
808  } else {
809  glEnable (GL_CULL_FACE);
810  glCullFace (GL_BACK);
811  glPolygonMode (GL_FRONT, GL_FILL);
812  }
813  }
814  if (drawing_style == G4ViewParameters::hlr) {
815  if (isTransparent) {
816  // Transparent - don't paint...
817  goto end_of_drawing_through_stencil;
818  }
819  }
820  if (isTransparent) {
821  // Transparent...
822  glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, painting_colour);
823  } else {
824  // Opaque...
825  glMaterialfv (GL_FRONT, GL_AMBIENT_AND_DIFFUSE, painting_colour);
826  }
827  glColor4fv (painting_colour);
828 #ifndef G4OPENGL_VERSION_2
829  glBegin (GL_QUADS);
830  glEdgeFlag (GL_TRUE);
831  fEdgeFlag = true;
832 #else
833  fEmulate_GL_QUADS = true;
834  glBeginVBO(GL_TRIANGLE_STRIP);
835 #endif
836 
837  for (int edgeCount = 0; edgeCount < 4; ++edgeCount) {
838 #ifndef G4OPENGL_VERSION_2
839  if (edgeFlag[edgeCount] > 0) {
840  if (fEdgeFlag != true) {
841  glEdgeFlag (GL_TRUE);
842  fEdgeFlag = true;
843  }
844  } else {
845  if (fEdgeFlag != false) {
846  glEdgeFlag (GL_FALSE);
847  fEdgeFlag = false;
848  }
849  }
850  glNormal3d (normals[edgeCount].x(),
851  normals[edgeCount].y(),
852  normals[edgeCount].z());
853  glVertex3d (vertex[edgeCount].x(),
854  vertex[edgeCount].y(),
855  vertex[edgeCount].z());
856 #else
857  fOglVertex.push_back(vertex[edgeCount].x());
858  fOglVertex.push_back(vertex[edgeCount].y());
859  fOglVertex.push_back(vertex[edgeCount].z());
860 
861  fOglVertex.push_back(normals[edgeCount].x());
862  fOglVertex.push_back(normals[edgeCount].y());
863  fOglVertex.push_back(normals[edgeCount].z());
864 
865 #endif
866  }
867 #ifndef G4OPENGL_VERSION_2
868  glEnd ();
869 #else
870  glEndVBO();
871 #endif
872  end_of_drawing_through_stencil:
873 
874  // and once more to reset the stencil bits...
875  glStencilFunc (GL_ALWAYS, 0, 1);
876  glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT);
877  glDepthFunc (GL_LEQUAL); // to make sure line gets drawn.
878  if (isTransparent) {
879  // Transparent...
880  glDisable (GL_CULL_FACE);
881  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
882  } else {
883  // Opaque...
884  if (clipping) {
885  glDisable (GL_CULL_FACE);
886  glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
887  } else {
888  glEnable (GL_CULL_FACE);
889  glCullFace (GL_BACK);
890  glPolygonMode (GL_FRONT, GL_LINE);
891  }
892  }
893  glDisable (GL_LIGHTING);
894  glColor4fv (current_colour);
895  fEdgeFlag = true;
896 #ifndef G4OPENGL_VERSION_2
897  glBegin (GL_QUADS);
898  glEdgeFlag (GL_TRUE);
899  fEdgeFlag = true;
900 #else
901  fEmulate_GL_QUADS = true;
902  glBeginVBO(GL_TRIANGLE_STRIP);
903 #endif
904  for (int edgeCount = 0; edgeCount < 4; ++edgeCount) {
905 #ifndef G4OPENGL_VERSION_2
906  if (edgeFlag[edgeCount] > 0) {
907  if (fEdgeFlag != true) {
908  glEdgeFlag (GL_TRUE);
909  fEdgeFlag = true;
910  }
911  } else {
912  if (fEdgeFlag != false) {
913  glEdgeFlag (GL_FALSE);
914  fEdgeFlag = false;
915  }
916  }
917  glNormal3d (normals[edgeCount].x(),
918  normals[edgeCount].y(),
919  normals[edgeCount].z());
920  glVertex3d (vertex[edgeCount].x(),
921  vertex[edgeCount].y(),
922  vertex[edgeCount].z());
923 #else
924  fOglVertex.push_back(vertex[edgeCount].x());
925  fOglVertex.push_back(vertex[edgeCount].y());
926  fOglVertex.push_back(vertex[edgeCount].z());
927 
928  fOglVertex.push_back(normals[edgeCount].x());
929  fOglVertex.push_back(normals[edgeCount].y());
930  fOglVertex.push_back(normals[edgeCount].z());
931 
932 #endif
933  }
934 #ifndef G4OPENGL_VERSION_2
935  glEnd ();
936 #else
937  glEndVBO();
938 #endif
939 
940  glDepthFunc (GL_LEQUAL); // Revert for next facet.
941  fEdgeFlag = true;
942 #ifndef G4OPENGL_VERSION_2
943  glBegin (GL_QUADS); // Ready for next facet. GL
944  glEdgeFlag (GL_TRUE);
945  fEdgeFlag = true;
946  // says it ignores incomplete
947  // quadrilaterals, so final empty
948  // glBegin/End sequence should be OK.
949 #else
950  fEmulate_GL_QUADS = true;
951  glBeginVBO(GL_TRIANGLE_STRIP);
952 #endif
953  }
954  } while (notLastFace);
955 
956 #ifndef G4OPENGL_VERSION_2
957  glEnd ();
958 #else
959 
960 // FIXME: du grand n'importe quoi en test
961 // Cube optimization
962 
963  // store old DrawType because in case of optimization it could be changed
964  GLenum oldDrawArrayType = fDrawArrayType;
965 
966  if (dynamic_cast<const G4PolyhedronTrd2*>(&polyhedron)) {
967 // OptimizeVBOForTrd();
968  } else if (dynamic_cast<const G4PolyhedronCons*>(&polyhedron)) {
969 // OptimizeVBOForCons((polyhedron.GetNoVertices()-2)/2 ); // top + bottom + all faces
970  }
971 
972  glEndVBO();
973  fDrawArrayType = oldDrawArrayType;
974 #endif
975 
976  glDisable (GL_STENCIL_TEST); // Revert to default for next primitive.
977  glDepthMask (GL_TRUE); // Revert to default for next primitive.
978 #ifndef G4OPENGL_VERSION_2
979  glDisable (GL_LIGHTING); // Revert to default for next primitive.
980 #endif
981 }
982 
983 void G4OpenGLSceneHandler::AddCompound(const G4VTrajectory& traj) {
984  G4VSceneHandler::AddCompound(traj); // For now.
985 }
986 
987 void G4OpenGLSceneHandler::AddCompound(const G4VHit& hit) {
988  G4VSceneHandler::AddCompound(hit); // For now.
989 }
990 
991 void G4OpenGLSceneHandler::AddCompound(const G4VDigi& digi) {
992  G4VSceneHandler::AddCompound(digi); // For now.
993 }
994 
995 void G4OpenGLSceneHandler::AddCompound(const G4THitsMap<G4double>& hits) {
996  G4VSceneHandler::AddCompound(hits); // For now.
997 }
998 
999 void G4OpenGLSceneHandler::AddCompound(const G4THitsMap<G4StatDouble>& hits) {
1000  G4VSceneHandler::AddCompound(hits); // For now.
1001 }
1002 
1003 
1004 #ifdef G4OPENGL_VERSION_2
1005 
1006 // Optimize vertex and indices in order to render less vertex in OpenGL VBO/IBO
1007 void G4OpenGLSceneHandler::OptimizeVBOForTrd(){
1008 
1009  /* HOW IT IS BUILD (as we receive it from fOglVertex :
1010  */
1011 
1012  std::vector<double> vertices;
1013  vertices.insert (vertices.end(),fOglVertex.begin(),fOglVertex.begin()+6*6); // ABCDEF
1014  vertices.insert (vertices.end(),fOglVertex.begin()+9*6,fOglVertex.begin()+9*6+6); // G
1015  vertices.insert (vertices.end(),fOglVertex.begin()+13*6,fOglVertex.begin()+13*6+6); // H
1016  fOglVertex = vertices;
1017 
1018  int myarray [] = {
1019  3,2,0,1,4,5,7,6, 6,0,4,3,7,2,6,1,5
1020  };
1021  fOglIndices.insert(fOglIndices.begin(), myarray, myarray+17/*36*/);
1022 
1023  fDrawArrayType = GL_TRIANGLE_STRIP;
1024 }
1025 
1026 // Optimize vertex and indices in order to render less vertex in OpenGL VBO/IBO
1027 void G4OpenGLSceneHandler::OptimizeVBOForCons(G4int aNoFaces){
1028  // Optimized, 1st level : 10f/15sec with 1000 cones
1029  // DrawElements:208 vertex and 605 (2*100+2*100+2*100+5) indices for a 100 face cone
1030 
1031  /* surface of polycone : could be optimized
1032  for 100 faces :
1033  - 100*4 = 400 points
1034  - 100*2+2 = 202 points with TRIANGLE_STRIP
1035  Total :
1036  n*4+n*4+n*4 = n*12
1037  optimize : n*2+2+1+n+1 = n*3+3 (factor 4)
1038  but could do better : n faces should give = n*2+2
1039  */
1040 
1041  /*
1042  0
1043  / \
1044  2---4 6 ....2
1045  | |
1046  3---5 7 ....3
1047  \ /
1048  1
1049  */
1050  // First, faces
1051  std::vector<double> vertices;
1052 
1053  // Add bottom and top vertex
1054  // aNoFaces*4*6+6 : nb Faces * 4 points per face * 6 vertex by point + 1 point offset
1055  vertices.insert (vertices.end(),fOglVertex.begin()+ (aNoFaces*4)*6,fOglVertex.begin()+(aNoFaces*4)*6+6); // 0
1056  vertices.insert (vertices.end(),fOglVertex.begin()+ (aNoFaces*8+1)*6,fOglVertex.begin()+(aNoFaces*8+1)*6+6); // 1
1057 
1058  // Add facets points
1059  G4int posInVertice;
1060  for (G4int a = 0; a<aNoFaces; a++) {
1061  posInVertice = a*4*6;
1062  vertices.insert (vertices.end(),fOglVertex.begin()+posInVertice,fOglVertex.begin()+posInVertice+1*6+6); // AB
1063  }
1064  vertices.insert (vertices.end(),fOglVertex.begin(),fOglVertex.begin()+1*6*6); // AB
1065  fOglVertex = vertices;
1066 
1067  // Add indices for top :
1068  // simple version : 0-2-0-4-0-6-0-8-0-10..
1069  // optimized version : 2-0-4-6- 6-0-8-10.. but we have to deal with odd faces numbers
1070  for (G4int a=0; a<aNoFaces; a++) {
1071  fOglIndices.push_back(0);
1072  fOglIndices.push_back(a*2+2);
1073  }
1074  // close strip
1075  fOglIndices.push_back(0);
1076  fOglIndices.push_back(2);
1077 
1078  // Add indices for faces
1079  for (G4int a = 0; a<aNoFaces; a++) {
1080  fOglIndices.push_back(a*2+2);
1081  fOglIndices.push_back(a*2+1+2);
1082  }
1083  fOglIndices.push_back(2);
1084  fOglIndices.push_back(2+1);
1085 
1086  // Second : top
1087  // 3-1-5-1-7-1-9-1..
1088  for (G4int a=0; a<aNoFaces; a++) {
1089  fOglIndices.push_back(a*2+3);
1090  fOglIndices.push_back(1);
1091  }
1092  // close strip
1093  fOglIndices.push_back(0+3);
1094 
1095  fDrawArrayType = GL_TRIANGLE_STRIP;
1096  fEmulate_GL_QUADS = false;
1097 }
1098 
1099 void G4OpenGLSceneHandler::glBeginVBO(GLenum type) {
1100  fDrawArrayType = type;
1101 #ifndef G4VIS_BUILD_OPENGLWT_DRIVER
1102  glGenBuffers(1,&fVertexBufferObject);
1103  glGenBuffers(1,&fIndicesBufferObject);
1104 #else
1105  fVertexBufferObject = glCreateBuffer(); //glGenBuffer(1,fVertexBufferObject_2)
1106  fIndicesBufferObject = glCreateBuffer(); //glGenBuffer(1,fIndicesBufferObject_2)
1107 #endif
1108 
1109  // clear data and indices for OpenGL
1110  fOglVertex.clear();
1111  fOglIndices.clear();
1112 }
1113 
1114 // 2 cases :
1115 /*
1116  glDrawArray : if there is no vertex indices : fOglIndices.size() == 0
1117  glDrawElements : if there is vertex indices : fOglIndices.size() != 0
1118 
1119  */
1120 void G4OpenGLSceneHandler::glEndVBO() {
1121  if (fOglIndices.size() == 0) {
1122 
1123 
1124  std::vector<double> vertices;
1125  // check if it is a GL_QUADS emulation
1126  if (fEmulate_GL_QUADS == true) {
1127  fEmulate_GL_QUADS = false;
1128  // A point has 6 double : Vx Vy Vz Nx Ny Nz
1129  // A QUAD should be like this
1130  /*
1131  0 3/4 7/8 ..
1132 
1133  1 2/5 6/9 ..
1134  */
1135  // And if 3==4 and 2==5, we should do it like this for a TRIANGLES_STRIP
1136  /*
1137  0 4 8 ..
1138  | / | / |
1139  1 5 9 ..
1140  // Optimized, 1st level : 24f/15sec with 10 cones
1141  // non Optimized, 1st level : 12f/15sec with 10 cones
1142  */
1143  // should be 4 points
1144  for (unsigned int a=0; a<fOglVertex.size(); a+=6*4) {
1145  vertices.insert (vertices.end(),fOglVertex.begin()+a,fOglVertex.begin()+a+1*6+6); // 0-1
1146  // if 2-3 == 4-5, do not add them
1147  // if differents, we are obliged to create a new GL_TRIANGLE_STRIP
1148  if (a+4*6+5 < fOglVertex.size()) {
1149  if ((fOglVertex[a+2*6+0] != fOglVertex[a+5*6+0]) || //Vx for 2 and 5
1150  (fOglVertex[a+2*6+1] != fOglVertex[a+5*6+1]) || //Vy for 2 and 5
1151  (fOglVertex[a+2*6+2] != fOglVertex[a+5*6+2]) || //Vz for 2 and 5
1152  (fOglVertex[a+2*6+3] != fOglVertex[a+5*6+3]) || //Px for 2 and 5
1153  (fOglVertex[a+2*6+4] != fOglVertex[a+5*6+4]) || //Py for 2 and 5
1154  (fOglVertex[a+2*6+5] != fOglVertex[a+5*6+5]) || //Pz for 2 and 5
1155 
1156  (fOglVertex[a+3*6+0] != fOglVertex[a+4*6+0]) || //Vx for 3 and 4
1157  (fOglVertex[a+3*6+1] != fOglVertex[a+4*6+1]) || //Vy for 3 and 4
1158  (fOglVertex[a+3*6+2] != fOglVertex[a+4*6+2]) || //Vz for 3 and 4
1159  (fOglVertex[a+3*6+3] != fOglVertex[a+4*6+3]) || //Px for 3 and 4
1160  (fOglVertex[a+3*6+4] != fOglVertex[a+4*6+4]) || //Py for 3 and 4
1161  (fOglVertex[a+3*6+5] != fOglVertex[a+4*6+5])) { //Pz for 3 and 4
1162  // add last points
1163  vertices.insert (vertices.end(),fOglVertex.begin()+a+3*6,fOglVertex.begin()+a+3*6+6); // 3
1164  vertices.insert (vertices.end(),fOglVertex.begin()+a+2*6,fOglVertex.begin()+a+2*6+6); // 2
1165  // build and send the GL_TRIANGLE_STRIP
1166  drawVBOArray(vertices);
1167  vertices.clear();
1168  }
1169  } else { // end of volume
1170  vertices.insert (vertices.end(),fOglVertex.begin()+a+3*6,fOglVertex.begin()+a+3*6+6); // 3
1171  vertices.insert (vertices.end(),fOglVertex.begin()+a+2*6,fOglVertex.begin()+a+2*6+6); // 2
1172  }
1173  }
1174  fOglVertex = vertices;
1175  }
1176 
1177  drawVBOArray(fOglVertex);
1178 
1179  } else {
1180 
1181  // Bind VBO
1182  glBindBuffer(GL_ARRAY_BUFFER, fVertexBufferObject);
1183 
1184  // Load fOglVertex into VBO
1185 #ifndef G4VIS_BUILD_OPENGLWT_DRIVER
1186  int sizeV = fOglVertex.size();
1187  // FIXME : perhaps a problem withBufferData in OpenGL other than WebGL ?
1188 // void glBufferData( GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
1189  glBufferData(GL_ARRAY_BUFFER, sizeof(double)*sizeV, &fOglVertex[0], GL_STATIC_DRAW);
1190 #else
1191  glBufferDatafv(GL_ARRAY_BUFFER, fOglVertex.begin(), fOglVertex.end(), GL_STATIC_DRAW);
1192 #endif
1193 
1194  // Bind IBO
1195  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, fIndicesBufferObject);
1196 
1197  // Load fOglVertex into VBO
1198 #ifndef G4VIS_BUILD_OPENGLWT_DRIVER
1199  int sizeI = fOglIndices.size();
1200  glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(int)*sizeI, &fOglIndices[0], GL_STATIC_DRAW);
1201 #else
1202  glBufferDataiv(GL_ELEMENT_ARRAY_BUFFER, fOglIndices.begin(), fOglIndices.end(), GL_STATIC_DRAW, GL_UNSIGNED_BYTE);
1203 #endif
1204 
1205  //----------------------------
1206  // Draw VBO
1207  //----------------------------
1208  glBindBuffer(GL_ARRAY_BUFFER, fVertexBufferObject);
1209  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, fIndicesBufferObject);
1210 
1211  // the fVertexPositionAttribute is inside the G4OpenGLViewer
1212  G4OpenGLViewer* pGLViewer = dynamic_cast<G4OpenGLViewer*>(fpViewer);
1213  if (pGLViewer) {
1214  glEnableVertexAttribArray(pGLViewer->fVertexPositionAttribute);
1215 
1216  glVertexAttribPointer(pGLViewer->fVertexPositionAttribute,
1217  3, // size: Every vertex has an X, Y anc Z component
1218  GL_FLOAT, // type: They are floats
1219  GL_FALSE, // normalized: Please, do NOT normalize the vertices
1220  2*3*4, // stride: The first byte of the next vertex is located this
1221  // amount of bytes further. The format of the VBO is
1222  // vx, vy, vz, nx, ny, nz and every element is a
1223  // Float32, hence 4 bytes large
1224  0); // offset: The byte position of the first vertex in the buffer
1225  }
1226 
1227 
1228  glBindBuffer(GL_ARRAY_BUFFER, fVertexBufferObject);
1229  glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, fIndicesBufferObject);
1230 // glDrawElements(fDrawArrayType, fOglIndices.size(), GL_UNSIGNED_SHORT, 0);
1231  glDrawElements(fDrawArrayType, fOglIndices.size(), GL_UNSIGNED_SHORT, 0);
1232 
1233  if (pGLViewer) {
1234  glDisableVertexAttribArray(pGLViewer->fVertexPositionAttribute);
1235  }
1236 
1237  // delete the buffer
1238 #ifndef G4VIS_BUILD_OPENGLWT_DRIVER
1239  glDeleteBuffers(1,&fVertexBufferObject);
1240 #else
1241  glDeleteBuffer(fVertexBufferObject);
1242 #endif
1243  }
1244 }
1245 
1246 void G4OpenGLSceneHandler::drawVBOArray(std::vector<double> vertices) {
1247 #ifndef G4VIS_BUILD_OPENGLWT_DRIVER
1248  glGenBuffers(1,&fVertexBufferObject);
1249  glGenBuffers(1,&fIndicesBufferObject);
1250 #else
1251  fVertexBufferObject = glCreateBuffer(); //glGenBuffer(1,fVertexBufferObject_2)
1252  fIndicesBufferObject = glCreateBuffer(); //glGenBuffer(1,fIndicesBufferObject_2)
1253 #endif
1254 
1255  // Bind this buffer
1256  glBindBuffer(GL_ARRAY_BUFFER, fVertexBufferObject);
1257  // Load oglData into VBO
1258 #ifndef G4VIS_BUILD_OPENGLWT_DRIVER
1259  int s = vertices.size();
1260  glBufferData(GL_ARRAY_BUFFER, sizeof(double)*s, &vertices[0], GL_STATIC_DRAW);
1261 #else
1262  glBufferDatafv(GL_ARRAY_BUFFER, vertices.begin(), vertices.end(), GL_STATIC_DRAW);
1263 #endif
1264 
1265  //----------------------------
1266  // Draw VBO
1267  //----------------------------
1268  glBindBuffer(GL_ARRAY_BUFFER, fVertexBufferObject);
1269 
1270  // the fVertexPositionAttribute is inside the G4OpenGLViewer
1271  G4OpenGLViewer* pGLViewer = dynamic_cast<G4OpenGLViewer*>(fpViewer);
1272  if (pGLViewer) {
1273  glEnableVertexAttribArray(pGLViewer->fVertexPositionAttribute);
1274 
1275 // glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer)
1276 
1277 /*
1278  GL_DOUBLE
1279  Warning: This section describes legacy OpenGL APIs that have been removed from core OpenGL 3.1 and above (they are only deprecated in OpenGL 3.0). It is recommended that you not use this functionality in your programs.
1280 
1281  glLoadMatrixd, glRotated and any other function that have to do with the double type. Most GPUs don't support GL_DOUBLE (double) so the driver will convert the data to GL_FLOAT (float) and send to the GPU. If you put GL_DOUBLE data in a VBO, the performance might even be much worst than immediate mode (immediate mode means glBegin, glVertex, glEnd). GL doesn't offer any better way to know what the GPU prefers.
1282  */
1283 #ifndef G4VIS_BUILD_OPENGLWT_DRIVER
1284  glVertexAttribPointer(pGLViewer->fVertexPositionAttribute,
1285  3, // size: Every vertex has an X, Y anc Z component
1286  GL_DOUBLE, // type: They are double
1287  GL_FALSE, // normalized: Please, do NOT normalize the vertices
1288  6*sizeof(double), // stride: The first byte of the next vertex is located this
1289  // amount of bytes further. The format of the VBO is
1290  // vx, vy, vz, nx, ny, nz and every element is a
1291  // Float32, hence 4 bytes large
1292  0); // offset: The byte position of the first vertex in the buffer
1293 #else
1294  glVertexAttribPointer(pGLViewer->fVertexPositionAttribute,
1295  3, // size: Every vertex has an X, Y anc Z component
1296  GL_FLOAT, // type: They are floats
1297  GL_FALSE, // normalized: Please, do NOT normalize the vertices
1298  2*3*4, // stride: The first byte of the next vertex is located this
1299  // amount of bytes further. The format of the VBO is
1300  // vx, vy, vz, nx, ny, nz and every element is a
1301  // Float32, hence 4 bytes large
1302  0); // offset: The byte position of the first vertex in the buffer
1303 #endif
1304  }
1305 
1306  glDrawArrays(fDrawArrayType, // GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES, GL_TRIANGLE_FAN, GL_TRIANGLE_STRIP, and GL_TRIANGLES
1307  0, vertices.size()/6);
1308  if (pGLViewer) {
1309 #ifndef G4VIS_BUILD_OPENGLWT_DRIVER
1310  glDisableClientState( GL_VERTEX_ARRAY );
1311 #else
1312  glDisableVertexAttribArray(pGLViewer->fVertexPositionAttribute);
1313 #endif
1314  }
1315 
1316  // delete the buffer
1317 #ifndef G4VIS_BUILD_OPENGLWT_DRIVER
1318  glDeleteBuffers(1,&fVertexBufferObject);
1319 #else
1320  glDeleteBuffer(fVertexBufferObject);
1321 #endif
1322 }
1323 #endif
1324 
1325 #endif
Definition: G4Text.hh:73
virtual G4VSolid * CreateSectionSolid()
MarkerType GetMarkerType() const
static constexpr double s
Definition: G4SIunits.hh:169
virtual void BeginPrimitives(const G4Transform3D &objectTransformation)
std::vector< ExP01TrackerHit * > a
Definition: ExP01Classes.hh:33
HepGeom::Point3D< G4double > G4Point3D
Definition: G4Point3D.hh:35
HepGeom::Vector3D< G4double > G4Vector3D
Definition: G4Vector3D.hh:35
Definition: G4VHit.hh:48
const char * name(G4int ptype)
G4Point3D GetPosition() const
int G4int
Definition: G4Types.hh:78
virtual void AddPrimitive(const G4Polyline &)=0
const G4Run * GetCurrentRun() const
static constexpr double twopi
Definition: G4SIunits.hh:76
G4int GetEventID() const
Definition: G4Event.hh:151
G4GLOB_DLL std::ostream G4cout
bool G4bool
Definition: G4Types.hh:79
static G4MTRunManager * GetMasterRunManager()
G4int GetRunID() const
Definition: G4Run.hh:76
Definition: G4Run.hh:46
virtual void EndPrimitives()
HepGeom::Transform3D G4Transform3D
G4bool IsMultithreadedApplication()
Definition: G4Threading.cc:152
virtual void BeginPrimitives2D(const G4Transform3D &objectTransformation)
static G4RunManager * GetRunManager()
Definition: G4RunManager.cc:79
virtual void AddCompound(const G4VTrajectory &)
virtual void ProcessScene()
virtual void PreAddSolid(const G4Transform3D &objectTransformation, const G4VisAttributes &)
FillStyle GetFillStyle() const
#define G4endl
Definition: G4ios.hh:61
static constexpr double pi
Definition: G4SIunits.hh:75
double G4double
Definition: G4Types.hh:76
virtual void EndPrimitives2D()
G4GLOB_DLL std::ostream G4cerr
HepGeom::Normal3D< G4double > G4Normal3D
Definition: G4Normal3D.hh:35