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