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