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