G4OpenGLViewer.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 //
00027 // $Id$
00028 //
00029 // 
00030 // Andrew Walkden  27th March 1996
00031 // OpenGL view - opens window, hard copy, etc.
00032 
00033 #ifdef G4VIS_BUILD_OPENGL_DRIVER
00034 
00035 #include "G4ios.hh"
00036 #include "G4SystemOfUnits.hh"
00037 #include "G4OpenGLViewer.hh"
00038 #include "G4OpenGLSceneHandler.hh"
00039 #include "G4OpenGLTransform3D.hh"
00040 #include "G4OpenGL2PSAction.hh"
00041 
00042 #include "G4Scene.hh"
00043 #include "G4VisExtent.hh"
00044 #include "G4LogicalVolume.hh"
00045 #include "G4VSolid.hh"
00046 #include "G4Point3D.hh"
00047 #include "G4Normal3D.hh"
00048 #include "G4Plane3D.hh"
00049 #include "G4AttHolder.hh"
00050 #include "G4AttCheck.hh"
00051 #include "G4Text.hh"
00052 
00053 // GL2PS
00054 #include "Geant4_gl2ps.h"
00055 
00056 #include <sstream>
00057 
00058 G4int G4OpenGLViewer::fPrintSizeX = -1;
00059 G4int G4OpenGLViewer::fPrintSizeY = -1;
00060 G4String G4OpenGLViewer::fPrintFilename = "G4OpenGL";
00061 int G4OpenGLViewer::fPrintFilenameIndex = 0;
00062 
00063 G4OpenGLViewer::G4OpenGLViewer (G4OpenGLSceneHandler& scene):
00064 G4VViewer (scene, -1),
00065 fPrintColour (true),
00066 fVectoredPs (true),
00067 fOpenGLSceneHandler(scene),
00068 background (G4Colour(0.,0.,0.)),
00069 transparency_enabled (true),
00070 antialiasing_enabled (false),
00071 haloing_enabled (false),
00072 fStartTime(-DBL_MAX),
00073 fEndTime(DBL_MAX),
00074 fFadeFactor(0.),
00075 fDisplayHeadTime(false),
00076 fDisplayHeadTimeX(-0.9),
00077 fDisplayHeadTimeY(-0.9),
00078 fDisplayHeadTimeSize(24.),
00079 fDisplayHeadTimeRed(0.),
00080 fDisplayHeadTimeGreen(1.),
00081 fDisplayHeadTimeBlue(1.),
00082 fDisplayLightFront(false),
00083 fDisplayLightFrontX(0.),
00084 fDisplayLightFrontY(0.),
00085 fDisplayLightFrontZ(0.),
00086 fDisplayLightFrontT(0.),
00087 fDisplayLightFrontRed(0.),
00088 fDisplayLightFrontGreen(1.),
00089 fDisplayLightFrontBlue(0.),
00090 fRot_sens(1.),
00091 fPan_sens(0.01),
00092 fWinSize_x(0),
00093 fWinSize_y(0),
00094 fPointSize (0),
00095 fSizeHasChanged(0),
00096 fGl2psDefaultLineWith(1),
00097 fGl2psDefaultPointSize(2)
00098 {
00099 #ifdef G4DEBUG_VIS_OGL
00100   printf("G4OpenGLViewer:: Creation\n");
00101 #endif
00102   // Make changes to view parameters for OpenGL...
00103   fVP.SetAutoRefresh(true);
00104   fDefaultVP.SetAutoRefresh(true);
00105 
00106   fGL2PSAction = new G4OpenGL2PSAction();
00107 
00108   //  glClearColor (0.0, 0.0, 0.0, 0.0);
00109   //  glClearDepth (1.0);
00110   //  glDisable (GL_BLEND);
00111   //  glDisable (GL_LINE_SMOOTH);
00112   //  glDisable (GL_POLYGON_SMOOTH);
00113 
00114 }
00115 
00116 G4OpenGLViewer::~G4OpenGLViewer ()
00117 {
00118   delete fGL2PSAction;
00119 }
00120 
00121 void G4OpenGLViewer::InitializeGLView () 
00122 {
00123 #ifdef G4DEBUG_VIS_OGL
00124   printf("G4OpenGLViewer::InitializeGLView\n");
00125 #endif
00126 
00127   fWinSize_x = fVP.GetWindowSizeHintX();
00128   fWinSize_y = fVP.GetWindowSizeHintY();
00129 
00130   glClearColor (0.0, 0.0, 0.0, 0.0);
00131   glClearDepth (1.0);
00132   glDisable (GL_LINE_SMOOTH);
00133   glDisable (GL_POLYGON_SMOOTH);
00134 
00135 // clear the buffers and window?
00136   ClearView ();
00137   FinishView ();
00138   
00139   glDepthFunc (GL_LEQUAL);
00140   glDepthMask (GL_TRUE);
00141   
00142   glEnable (GL_BLEND);
00143   glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00144   
00145 #ifdef G4DEBUG_VIS_OGL
00146   printf("G4OpenGLViewer::InitializeGLView END\n");
00147 #endif
00148 }  
00149 
00150 void G4OpenGLViewer::ClearView () {
00151 #ifdef G4DEBUG_VIS_OGL
00152   printf("G4OpenGLViewer::ClearView\n");
00153 #endif
00154   glClearColor (background.GetRed(),
00155                 background.GetGreen(),
00156                 background.GetBlue(),
00157                 1.);
00158   glClearDepth (1.0);
00159   //Below line does not compile with Mesa includes. 
00160   //glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
00161   glClear (GL_COLOR_BUFFER_BIT);
00162   glClear (GL_DEPTH_BUFFER_BIT);
00163   glClear (GL_STENCIL_BUFFER_BIT);
00164 #ifdef G4DEBUG_VIS_OGL
00165   printf("G4OpenGLViewer::ClearView flush\n");
00166 #endif
00167   glFlush ();
00168 }
00169 
00170 
00171 void G4OpenGLViewer::ResizeWindow(unsigned int aWidth, unsigned int aHeight) {
00172   if ((fWinSize_x != aWidth) || (fWinSize_y != aHeight)) {
00173     fWinSize_x = aWidth;
00174     fWinSize_y = aHeight;
00175     fSizeHasChanged = true;
00176   } else {
00177     fSizeHasChanged = false;
00178   }
00179 }
00180 
00187 void G4OpenGLViewer::ResizeGLView()
00188 {
00189 #ifdef G4DEBUG_VIS_OGL
00190   printf("G4OpenGLViewer::ResizeGLView %d %d %#lx\n",fWinSize_x,fWinSize_y,(unsigned long)this);
00191 #endif
00192   // Check size
00193   GLint dims[2];
00194   dims[0] = 0;
00195   dims[1] = 0;
00196 
00197   glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
00198 
00199   if ((dims[0] !=0 ) && (dims[1] !=0)) {
00200 
00201     if (fWinSize_x > (unsigned)dims[0]) {
00202       G4cerr << "Try to resize view greater than max X viewport dimension. Desired size "<<fWinSize_x <<" is resize to "<<  dims[0] << G4endl;
00203       fWinSize_x = dims[0];
00204     }
00205     if (fWinSize_y > (unsigned)dims[1]) {
00206       G4cerr << "Try to resize view greater than max Y viewport dimension. Desired size "<<fWinSize_y <<" is resize to "<<  dims[1] << G4endl;
00207       fWinSize_y = dims[1];
00208     }
00209   }
00210     
00211   glViewport(0, 0, fWinSize_x,fWinSize_y);   
00212 
00213 
00214 }
00215 
00216 
00217 void G4OpenGLViewer::SetView () {
00218 
00219   if (!fSceneHandler.GetScene()) {
00220     return;
00221   }
00222   // Calculates view representation based on extent of object being
00223   // viewed and (initial) viewpoint.  (Note: it can change later due
00224   // to user interaction via visualization system's GUI.)
00225   
00226   // Lighting.
00227   GLfloat lightPosition [4];
00228   lightPosition [0] = fVP.GetActualLightpointDirection().x();
00229   lightPosition [1] = fVP.GetActualLightpointDirection().y();
00230   lightPosition [2] = fVP.GetActualLightpointDirection().z();
00231   lightPosition [3] = 0.;
00232   // Light position is "true" light direction, so must come after gluLookAt.
00233   GLfloat ambient [] = { 0.2, 0.2, 0.2, 1.};
00234   GLfloat diffuse [] = { 0.8, 0.8, 0.8, 1.};
00235   glEnable (GL_LIGHT0);
00236   glLightfv (GL_LIGHT0, GL_AMBIENT, ambient);
00237   glLightfv (GL_LIGHT0, GL_DIFFUSE, diffuse);
00238   
00239   G4double ratioX = 1;
00240   G4double ratioY = 1;
00241   if (fWinSize_y > fWinSize_x) {
00242     ratioX = ((G4double)fWinSize_y) / ((G4double)fWinSize_x);
00243   }
00244   if (fWinSize_x > fWinSize_y) {
00245     ratioY = ((G4double)fWinSize_x) / ((G4double)fWinSize_y);
00246   }
00247   
00248   // Get radius of scene, etc.
00249   // Note that this procedure properly takes into account zoom, dolly and pan.
00250   const G4Point3D targetPoint
00251     = fSceneHandler.GetScene()->GetStandardTargetPoint()
00252     + fVP.GetCurrentTargetPoint ();
00253   G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
00254   if(radius<=0.) radius = 1.;
00255   const G4double cameraDistance = fVP.GetCameraDistance (radius);
00256   const G4Point3D cameraPosition =
00257     targetPoint + cameraDistance * fVP.GetViewpointDirection().unit();
00258   const GLdouble pnear  = fVP.GetNearDistance (cameraDistance, radius);
00259   const GLdouble pfar   = fVP.GetFarDistance  (cameraDistance, pnear, radius);
00260   const GLdouble right  = fVP.GetFrontHalfHeight (pnear, radius) * ratioY;
00261   const GLdouble left   = -right;
00262   const GLdouble top    = fVP.GetFrontHalfHeight (pnear, radius) * ratioX;
00263   const GLdouble bottom = -top;
00264   
00265   // FIXME
00266   ResizeGLView();
00267   //SHOULD SetWindowsSizeHint()...
00268 
00269   glMatrixMode (GL_PROJECTION); // set up Frustum.
00270   glLoadIdentity();
00271 
00272   const G4Vector3D scaleFactor = fVP.GetScaleFactor();
00273   glScaled(scaleFactor.x(),scaleFactor.y(),scaleFactor.z());
00274   
00275   if (fVP.GetFieldHalfAngle() == 0.) {
00276     glOrtho (left, right, bottom, top, pnear, pfar);
00277   }
00278   else {
00279     glFrustum (left, right, bottom, top, pnear, pfar);
00280   }  
00281 
00282   glMatrixMode (GL_MODELVIEW); // apply further transformations to scene.
00283   glLoadIdentity();
00284   
00285   const G4Normal3D& upVector = fVP.GetUpVector ();  
00286   G4Point3D gltarget;
00287   if (cameraDistance > 1.e-6 * radius) {
00288     gltarget = targetPoint;
00289   }
00290   else {
00291     gltarget = targetPoint - radius * fVP.GetViewpointDirection().unit();
00292   }
00293 
00294   const G4Point3D& pCamera = cameraPosition;  // An alias for brevity.
00295   gluLookAt (pCamera.x(),  pCamera.y(),  pCamera.z(),       // Viewpoint.
00296              gltarget.x(), gltarget.y(), gltarget.z(),      // Target point.
00297              upVector.x(), upVector.y(), upVector.z());     // Up vector.
00298 
00299   // Light position is "true" light direction, so must come after gluLookAt.
00300   glLightfv (GL_LIGHT0, GL_POSITION, lightPosition);
00301 
00302   // OpenGL no longer seems to reconstruct clipped edges, so, when the
00303   // BooleanProcessor is up to it, abandon this and use generic
00304   // clipping in G4OpenGLSceneHandler::CreateSectionPolyhedron.  Also,
00305   // force kernel visit on change of clipping plane in
00306   // G4OpenGLStoredViewer::CompareForKernelVisit.
00307   //if (fVP.IsSection () ) {  // pair of back to back clip planes.
00308   if (false) {  // pair of back to back clip planes.
00309     const G4Plane3D& sp = fVP.GetSectionPlane ();
00310     double sArray[4];
00311     sArray[0] = sp.a();
00312     sArray[1] = sp.b();
00313     sArray[2] = sp.c();
00314     sArray[3] = sp.d() + radius * 1.e-05;
00315     glClipPlane (GL_CLIP_PLANE0, sArray);
00316     glEnable (GL_CLIP_PLANE0);
00317     sArray[0] = -sp.a();
00318     sArray[1] = -sp.b();
00319     sArray[2] = -sp.c();
00320     sArray[3] = -sp.d() + radius * 1.e-05;
00321     glClipPlane (GL_CLIP_PLANE1, sArray);
00322     glEnable (GL_CLIP_PLANE1);
00323   } else {
00324     glDisable (GL_CLIP_PLANE0);
00325     glDisable (GL_CLIP_PLANE1);
00326   }
00327 
00328   // What we call intersection of cutaways is easy in OpenGL.  You
00329   // just keep cutting.  Unions are more tricky - you have to have
00330   // multiple passes and this is handled in
00331   // G4OpenGLImmediate/StoredViewer::ProcessView.
00332   const G4Planes& cutaways = fVP.GetCutawayPlanes();
00333   size_t nPlanes = cutaways.size();
00334   if (fVP.IsCutaway() &&
00335       fVP.GetCutawayMode() == G4ViewParameters::cutawayIntersection &&
00336       nPlanes > 0) {
00337     double a[4];
00338     a[0] = cutaways[0].a();
00339     a[1] = cutaways[0].b();
00340     a[2] = cutaways[0].c();
00341     a[3] = cutaways[0].d();
00342     glClipPlane (GL_CLIP_PLANE2, a);
00343     glEnable (GL_CLIP_PLANE2);
00344     if (nPlanes > 1) {
00345       a[0] = cutaways[1].a();
00346       a[1] = cutaways[1].b();
00347       a[2] = cutaways[1].c();
00348       a[3] = cutaways[1].d();
00349       glClipPlane (GL_CLIP_PLANE3, a);
00350       glEnable (GL_CLIP_PLANE3);
00351     }
00352     if (nPlanes > 2) {
00353       a[0] = cutaways[2].a();
00354       a[1] = cutaways[2].b();
00355       a[2] = cutaways[2].c();
00356       a[3] = cutaways[2].d();
00357       glClipPlane (GL_CLIP_PLANE4, a);
00358       glEnable (GL_CLIP_PLANE4);
00359     }
00360   } else {
00361     glDisable (GL_CLIP_PLANE2);
00362     glDisable (GL_CLIP_PLANE3);
00363     glDisable (GL_CLIP_PLANE4);
00364   }
00365 
00366   // Background.
00367   background = fVP.GetBackgroundColour ();
00368 
00369 }
00370 
00371 
00372 
00373 void G4OpenGLViewer::ResetView () {
00374   G4VViewer::ResetView();
00375   fRot_sens = 1;
00376   fPan_sens = 0.01;
00377 }
00378 
00379 
00380 void G4OpenGLViewer::HaloingFirstPass () {
00381   
00382   //To perform haloing, first Draw all information to the depth buffer
00383   //alone, using a chunky line width, and then Draw all info again, to
00384   //the colour buffer, setting a thinner line width an the depth testing 
00385   //function to less than or equal, so if two lines cross, the one 
00386   //passing behind the other will not pass the depth test, and so not
00387   //get rendered either side of the infront line for a short distance.
00388 
00389   //First, disable writing to the colo(u)r buffer...
00390   glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
00391 
00392   //Now enable writing to the depth buffer...
00393   glDepthMask (GL_TRUE);
00394   glDepthFunc (GL_LESS);
00395   glClearDepth (1.0);
00396 
00397   //Finally, set the line width to something wide...
00398   ChangeLineWidth(3.0);
00399 
00400 }
00401 
00402 void G4OpenGLViewer::HaloingSecondPass () {
00403 
00404   //And finally, turn the colour buffer back on with a sesible line width...
00405   glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
00406   glDepthFunc (GL_LEQUAL);
00407   ChangeLineWidth(1.0);
00408 
00409 }
00410 
00411 void G4OpenGLViewer::Pick(GLdouble x, GLdouble y)
00412 {
00413   //G4cout << "X: " << x << ", Y: " << y << G4endl;
00414   const G4int BUFSIZE = 512;
00415   GLuint selectBuffer[BUFSIZE];
00416   glSelectBuffer(BUFSIZE, selectBuffer);
00417   glRenderMode(GL_SELECT);
00418   glInitNames();
00419   glPushName(0);
00420   glMatrixMode(GL_PROJECTION);
00421   G4double currentProjectionMatrix[16];
00422   glGetDoublev(GL_PROJECTION_MATRIX, currentProjectionMatrix);
00423   glPushMatrix();
00424   glLoadIdentity();
00425   GLint viewport[4];
00426   glGetIntegerv(GL_VIEWPORT, viewport);
00427   // Define 5x5 pixel pick area
00428   gluPickMatrix(x, viewport[3] - y, 5., 5., viewport);
00429   glMultMatrixd(currentProjectionMatrix);
00430   glMatrixMode(GL_MODELVIEW);
00431   DrawView();
00432   GLint hits = glRenderMode(GL_RENDER);
00433   if (hits < 0)
00434     G4cout << "Too many hits.  Zoom in to reduce overlaps." << G4endl;
00435   else if (hits > 0) {
00436     G4cout << hits << " hit(s)" << G4endl;
00437     GLuint* p = selectBuffer;
00438     for (GLint i = 0; i < hits; ++i) {
00439       GLuint nnames = *p++;
00440       // This bit of debug code or...
00441       //GLuint zmin = *p++;
00442       //GLuint zmax = *p++;
00443       //G4cout << "Hit " << i << ": " << nnames << " names"
00444       //       << "\nzmin: " << zmin << ", zmax: " << zmax << G4endl;
00445       // ...just increment the pointer
00446       p++;
00447       p++;
00448       for (GLuint j = 0; j < nnames; ++j) {
00449         GLuint name = *p++;
00450         G4cout << "Hit: " << i
00451                << ", Sub-hit: " << j
00452                << ", PickName: " << name << G4endl;
00453         std::map<GLuint, G4AttHolder*>::iterator iter =
00454           fOpenGLSceneHandler.fPickMap.find(name);
00455         if (iter != fOpenGLSceneHandler.fPickMap.end()) {
00456           G4AttHolder* attHolder = iter->second;
00457           if(attHolder && attHolder->GetAttDefs().size()) {
00458             for (size_t iAtt = 0;
00459                  iAtt < attHolder->GetAttDefs().size(); ++iAtt) {
00460               G4cout << G4AttCheck(attHolder->GetAttValues()[iAtt],
00461                                    attHolder->GetAttDefs()[iAtt]);
00462             }
00463           }
00464         }
00465       }
00466       G4cout << G4endl;
00467     }
00468   }
00469   glMatrixMode(GL_PROJECTION);
00470   glPopMatrix();
00471   glMatrixMode(GL_MODELVIEW);
00472 }
00473 
00474 
00475 
00476 
00477 GLubyte* G4OpenGLViewer::grabPixels (int inColor, unsigned int width, unsigned int height) {
00478   
00479   GLubyte* buffer;
00480   GLint swapbytes, lsbfirst, rowlength;
00481   GLint skiprows, skippixels, alignment;
00482   GLenum format;
00483   int size;
00484 
00485   if (inColor) {
00486     format = GL_RGB;
00487     size = width*height*3;
00488   } else {
00489     format = GL_LUMINANCE;
00490     size = width*height*1;
00491   }
00492 
00493   buffer = new GLubyte[size];
00494   if (buffer == NULL)
00495     return NULL;
00496 
00497   glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes);
00498   glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst);
00499   glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength);
00500 
00501   glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows);
00502   glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels);
00503   glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment);
00504 
00505   glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE);
00506   glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE);
00507   glPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
00508 
00509   glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
00510   glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
00511   glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
00512 
00513   glReadBuffer(GL_FRONT);
00514   glReadPixels (0, 0, (GLsizei)width, (GLsizei)height, format, GL_UNSIGNED_BYTE, (GLvoid*) buffer);
00515 
00516   glPixelStorei (GL_UNPACK_SWAP_BYTES, swapbytes);
00517   glPixelStorei (GL_UNPACK_LSB_FIRST, lsbfirst);
00518   glPixelStorei (GL_UNPACK_ROW_LENGTH, rowlength);
00519   
00520   glPixelStorei (GL_UNPACK_SKIP_ROWS, skiprows);
00521   glPixelStorei (GL_UNPACK_SKIP_PIXELS, skippixels);
00522   glPixelStorei (GL_UNPACK_ALIGNMENT, alignment);
00523   
00524   return buffer;
00525 }
00526 
00527 void G4OpenGLViewer::printEPS() {
00528   bool res;
00529 #ifdef G4DEBUG_VIS_OGL
00530   printf("G4OpenGLViewer::printEPS file:%s Vec:%d Name:%s\n",getRealPrintFilename().c_str(),fVectoredPs,GetName().c_str());
00531 #endif
00532 
00533   // Change the LC_NUMERIC value in order to have "." separtor and not ","
00534   // This case is only useful for French, Canadien...
00535   size_t len = strlen(setlocale(LC_NUMERIC,NULL));
00536   char* oldLocale = (char*)(malloc(len+1));
00537   if(oldLocale!=NULL) strncpy(oldLocale,setlocale(LC_NUMERIC,NULL),len);
00538   setlocale(LC_NUMERIC,"C");
00539 
00540   if (fVectoredPs) {
00541     res = printVectoredEPS();
00542   } else {
00543     res = printNonVectoredEPS();
00544   }
00545 
00546   // restore the local
00547   if (oldLocale) {
00548     setlocale(LC_NUMERIC,oldLocale);
00549     free(oldLocale);
00550   }
00551 
00552   if (res == false) {
00553     G4cerr << "Error while saving file... "<<getRealPrintFilename().c_str()<< G4endl;
00554   } else {
00555     G4cout << "File "<<getRealPrintFilename().c_str()<<" has been saved " << G4endl;
00556   }
00557 
00558   // increment index if necessary
00559   if ( fPrintFilenameIndex != -1) {
00560     fPrintFilenameIndex++;
00561   }
00562 
00563 #ifdef G4DEBUG_VIS_OGL
00564   printf("G4OpenGLViewer::printEPS END\n");
00565 #endif
00566 }
00567 
00568 bool G4OpenGLViewer::printVectoredEPS() {
00569   return printGl2PS();
00570 }
00571 
00572 bool G4OpenGLViewer::printNonVectoredEPS () {
00573 
00574   int width = getRealPrintSizeX();
00575   int height = getRealPrintSizeY();
00576 
00577 #ifdef G4DEBUG_VIS_OGL
00578   printf("G4OpenGLViewer::printNonVectoredEPS file:%s Vec:%d X:%d Y:%d col:%d fWinX:%d fWinY:%d\n",getRealPrintFilename().c_str(),fVectoredPs,width,height,fPrintColour,fWinSize_x,fWinSize_y);
00579 #endif
00580   FILE* fp;
00581   GLubyte* pixels;
00582   GLubyte* curpix;
00583   int components, pos, i;
00584 
00585   pixels = grabPixels (fPrintColour, width, height);
00586 
00587   if (pixels == NULL) {
00588       G4cerr << "Failed to get pixels from OpenGl viewport" << G4endl;
00589     return false;
00590   }
00591   if (fPrintColour) {
00592     components = 3;
00593   } else {
00594     components = 1;
00595   }
00596   std::string name = getRealPrintFilename();
00597   fp = fopen (name.c_str(), "w");
00598   if (fp == NULL) {
00599     G4cerr << "Can't open filename " << name.c_str() << G4endl;
00600     return false;
00601   }
00602   
00603   fprintf (fp, "%%!PS-Adobe-2.0 EPSF-1.2\n");
00604   fprintf (fp, "%%%%Title: %s\n", name.c_str());
00605   fprintf (fp, "%%%%Creator: OpenGL pixmap render output\n");
00606   fprintf (fp, "%%%%BoundingBox: 0 0 %d %d\n", width, height);
00607   fprintf (fp, "%%%%EndComments\n");
00608   fprintf (fp, "gsave\n");
00609   fprintf (fp, "/bwproc {\n");
00610   fprintf (fp, "    rgbproc\n");
00611   fprintf (fp, "    dup length 3 idiv string 0 3 0 \n");
00612   fprintf (fp, "    5 -1 roll {\n");
00613   fprintf (fp, "    add 2 1 roll 1 sub dup 0 eq\n");
00614   fprintf (fp, "    { pop 3 idiv 3 -1 roll dup 4 -1 roll dup\n");
00615   fprintf (fp, "       3 1 roll 5 -1 roll } put 1 add 3 0 \n");
00616   fprintf (fp, "    { 2 1 roll } ifelse\n");
00617   fprintf (fp, "    }forall\n");
00618   fprintf (fp, "    pop pop pop\n");
00619   fprintf (fp, "} def\n");
00620   fprintf (fp, "systemdict /colorimage known not {\n");
00621   fprintf (fp, "   /colorimage {\n");
00622   fprintf (fp, "       pop\n");
00623   fprintf (fp, "       pop\n");
00624   fprintf (fp, "       /rgbproc exch def\n");
00625   fprintf (fp, "       { bwproc } image\n");
00626   fprintf (fp, "   }  def\n");
00627   fprintf (fp, "} if\n");
00628   fprintf (fp, "/picstr %d string def\n", width * components);
00629   fprintf (fp, "%d %d scale\n", width, height);
00630   fprintf (fp, "%d %d %d\n", width, height, 8);
00631   fprintf (fp, "[%d 0 0 %d 0 0]\n", width, height);
00632   fprintf (fp, "{currentfile picstr readhexstring pop}\n");
00633   fprintf (fp, "false %d\n", components);
00634   fprintf (fp, "colorimage\n");
00635   
00636   curpix = (GLubyte*) pixels;
00637   pos = 0;
00638   for (i = width*height*components; i>0; i--) {
00639     fprintf (fp, "%02hx ", (unsigned short)(*(curpix++)));
00640     if (++pos >= 32) {
00641       fprintf (fp, "\n");
00642       pos = 0; 
00643     }
00644   }
00645   if (pos)
00646     fprintf (fp, "\n");
00647 
00648   fprintf (fp, "grestore\n");
00649   fprintf (fp, "showpage\n");
00650   delete [] pixels;
00651   fclose (fp);
00652 
00653   // Reset for next time (useful is size change)
00654   //  fPrintSizeX = -1;
00655   //  fPrintSizeY = -1;
00656 
00657   return true;
00658 }
00659 
00662 bool G4OpenGLViewer::isGl2psWriting() {
00663 
00664   if (!fGL2PSAction) return false;
00665   if (fGL2PSAction->fileWritingEnabled()) {
00666     return true;
00667   }
00668   return false;
00669 }
00670 
00671 
00672 /* Draw Gl2Ps text if needed
00673  */
00674 void G4OpenGLViewer::DrawText(const G4Text& g4text)
00675 {
00676   // gl2ps or GL window ?
00677   if (isGl2psWriting()) {
00678 
00679     G4VSceneHandler::MarkerSizeType sizeType;
00680     G4double size = fSceneHandler.GetMarkerSize(g4text,sizeType);
00681     G4Point3D position = g4text.GetPosition();
00682 
00683     G4String textString = g4text.GetText();
00684     const char* textCString = textString.c_str();
00685 
00686     glRasterPos3d(position.x(),position.y(),position.z());
00687     GLint align = GL2PS_TEXT_B;
00688 
00689     switch (g4text.GetLayout()) {
00690     case G4Text::left: align = GL2PS_TEXT_BL; break;
00691     case G4Text::centre: align = GL2PS_TEXT_B; break;
00692     case G4Text::right: align = GL2PS_TEXT_BR;
00693     }
00694     
00695     gl2psTextOpt(textCString,"Times-Roman",GLshort(size),align,0);
00696 
00697   } else {
00698 
00699     static G4int callCount = 0;
00700     ++callCount;
00701     //if (callCount <= 10 || callCount%100 == 0) {
00702     if (callCount <= 1) {
00703       G4cout <<
00704         "G4OpenGLViewer::DrawText: Not implemented for \""
00705              << fName <<
00706         "\"\n  Called with "
00707              << g4text
00708              << G4endl;
00709     }
00710   }
00711 }
00712 
00715 void G4OpenGLViewer::ChangePointSize(G4double size) {
00716 
00717   if (isGl2psWriting()) {
00718     fGL2PSAction->setPointSize(int(size));
00719   } else {
00720     glPointSize (size);
00721   }
00722 }
00723 
00724 
00727 void G4OpenGLViewer::ChangeLineWidth(G4double width) {
00728 
00729   if (isGl2psWriting()) {
00730     fGL2PSAction->setLineWidth(int(width));
00731   } else {
00732     glLineWidth (width);
00733   }
00734 }
00735 
00736 
00737 bool G4OpenGLViewer::printGl2PS() {
00738 
00739   int width = getRealPrintSizeX();
00740   int height = getRealPrintSizeY();
00741 
00742   if (!fGL2PSAction) return false;
00743 
00744   fGL2PSAction->setFileName(getRealPrintFilename().c_str());
00745   // try to resize
00746   int X = fWinSize_x;
00747   int Y = fWinSize_y;
00748 
00749   fWinSize_x = width;
00750   fWinSize_y = height;
00751   // Laurent G. 16/03/10 : Not the good way to do. 
00752   // We should draw in a new offscreen context instead of
00753   // resizing and drawing in current window...
00754   // This should be solve when we will do an offscreen method
00755   // to render OpenGL
00756   // See : 
00757   // http://developer.apple.com/Mac/library/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_offscreen/opengl_offscreen.html
00758   // http://www.songho.ca/opengl/gl_fbo.html
00759 
00760    ResizeGLView();
00761    bool extendBuffer = true;
00762    bool endWriteAction = false;
00763    bool beginWriteAction = true;
00764    while ((extendBuffer) && (! endWriteAction)) {
00765      
00766      beginWriteAction = fGL2PSAction->enableFileWriting();
00767      if (beginWriteAction) {
00768        
00769        // Set the viewport
00770        //    fGL2PSAction->setViewport(0, 0, getRealPrintSizeX(),getRealPrintSizeY());  
00771        // By default, we choose the line width (trajectories...)
00772        fGL2PSAction->setLineWidth(fGl2psDefaultLineWith);
00773        // By default, we choose the point size (markers...)
00774        fGL2PSAction->setPointSize(fGl2psDefaultPointSize);
00775        
00776        DrawView ();
00777        endWriteAction = fGL2PSAction->disableFileWriting();
00778      }
00779      if ((! endWriteAction) || (! beginWriteAction)) {
00780        extendBuffer = fGL2PSAction->extendBufferSize();
00781      }
00782    }
00783    fGL2PSAction->resetBufferSizeParameters();
00784 
00785    if (!extendBuffer ) {
00786      G4cerr << "gl2ps buffer size is not big enough to print this geometry. Thy to extend it. No output produced"<< G4endl;
00787    }
00788    if (!beginWriteAction ) {
00789      G4cerr << "Error while writing in the file "<<getRealPrintFilename().c_str()<<". Check read/write access No output produced" << G4endl;
00790    }
00791    if (!endWriteAction ) {
00792      G4cerr << "gl2ps error. No output produced" << G4endl;
00793    }
00794   fWinSize_x = X;
00795   fWinSize_y = Y;
00796 
00797   // Reset for next time (useful is size change)
00798   //  fPrintSizeX = 0;
00799   //  fPrintSizeY = 0;
00800 
00801   return true;
00802 }
00803 
00804 unsigned int G4OpenGLViewer::getWinWidth() {
00805   return fWinSize_x;
00806 }
00807 
00808 unsigned int G4OpenGLViewer::getWinHeight() {
00809   return fWinSize_y;
00810 }
00811 
00812 G4bool G4OpenGLViewer::sizeHasChanged() {
00813   return fSizeHasChanged;
00814 }
00815 
00816 G4int G4OpenGLViewer::getRealPrintSizeX() {
00817   if (fPrintSizeX == -1) {
00818     return fWinSize_x;
00819   }
00820   GLint dims[2];
00821   glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
00822 
00823   // L.Garnier 01-2010: Some problems with mac 10.6
00824   if ((dims[0] !=0 ) && (dims[1] !=0)) {
00825     if (fPrintSizeX > dims[0]){
00826       return dims[0];
00827     }
00828   }
00829   if (fPrintSizeX < -1){
00830     return 0;
00831   }
00832   return fPrintSizeX;
00833 }
00834 
00835 G4int G4OpenGLViewer::getRealPrintSizeY() {
00836   if (fPrintSizeY == -1) {
00837     return fWinSize_y;
00838   }
00839   GLint dims[2];
00840   glGetIntegerv(GL_MAX_VIEWPORT_DIMS, dims);
00841 
00842   // L.Garnier 01-2010: Some problems with mac 10.6
00843   if ((dims[0] !=0 ) && (dims[1] !=0)) {
00844     if (fPrintSizeY > dims[1]){
00845       return dims[1];
00846     }
00847   }
00848   if (fPrintSizeY < -1){
00849     return 0;
00850   }
00851   return fPrintSizeY;
00852 }
00853 
00854 void G4OpenGLViewer::setPrintSize(G4int X, G4int Y) {
00855   fPrintSizeX = X;
00856   fPrintSizeY = Y;
00857 }
00858 
00859 void G4OpenGLViewer::setPrintFilename(G4String name,G4bool inc) {
00860   if (name != "") {
00861     fPrintFilename = name;
00862   } else {
00863     fPrintFilename = "G4OpenGL";  // by default
00864   }
00865   if (inc) {
00866     fPrintFilenameIndex=0;
00867   } else {
00868     fPrintFilenameIndex=-1;
00869   }
00870 }
00871 
00872 std::string G4OpenGLViewer::getRealPrintFilename() {
00873   std::string temp = fPrintFilename;
00874   if (fPrintFilenameIndex != -1) {
00875     temp += std::string("_");
00876     std::ostringstream os;
00877     os << fPrintFilenameIndex;
00878     std::string nb_str = os.str();
00879     temp += nb_str;
00880   }
00881   temp += ".eps";
00882   return temp;
00883 }
00884 
00885 GLdouble G4OpenGLViewer::getSceneNearWidth()
00886 {
00887   if (!fSceneHandler.GetScene()) {
00888     return 0;
00889   }
00890   const G4Point3D targetPoint
00891     = fSceneHandler.GetScene()->GetStandardTargetPoint()
00892     + fVP.GetCurrentTargetPoint ();
00893   G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
00894   if(radius<=0.) radius = 1.;
00895   const G4double cameraDistance = fVP.GetCameraDistance (radius);
00896   const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
00897   return 2 * fVP.GetFrontHalfHeight (pnear, radius);
00898 }
00899 
00900 GLdouble G4OpenGLViewer::getSceneFarWidth()
00901 {
00902   if (!fSceneHandler.GetScene()) {
00903     return 0;
00904   }
00905   const G4Point3D targetPoint
00906     = fSceneHandler.GetScene()->GetStandardTargetPoint()
00907     + fVP.GetCurrentTargetPoint ();
00908   G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
00909   if(radius<=0.) radius = 1.;
00910   const G4double cameraDistance = fVP.GetCameraDistance (radius);
00911   const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
00912   const GLdouble pfar    = fVP.GetFarDistance  (cameraDistance, pnear, radius);
00913   return 2 * fVP.GetFrontHalfHeight (pfar, radius);
00914 }
00915 
00916 
00917 GLdouble G4OpenGLViewer::getSceneDepth()
00918 {
00919   if (!fSceneHandler.GetScene()) {
00920     return 0;
00921   }
00922   const G4Point3D targetPoint
00923     = fSceneHandler.GetScene()->GetStandardTargetPoint()
00924     + fVP.GetCurrentTargetPoint ();
00925   G4double radius = fSceneHandler.GetScene()->GetExtent().GetExtentRadius();
00926   if(radius<=0.) radius = 1.;
00927   const G4double cameraDistance = fVP.GetCameraDistance (radius);
00928   const GLdouble pnear   = fVP.GetNearDistance (cameraDistance, radius);
00929   return fVP.GetFarDistance  (cameraDistance, pnear, radius)- pnear;
00930 }
00931 
00932 
00933 
00934 void G4OpenGLViewer::rotateScene(G4double dx, G4double dy)
00935 {
00936   if (fVP.GetRotationStyle() == G4ViewParameters::freeRotation) {
00937     rotateSceneInViewDirection(dx,dy);
00938   } else {
00939     if( dx != 0) {
00940       rotateSceneThetaPhi(dx,0);
00941     }
00942     if( dy != 0) {
00943       rotateSceneThetaPhi(0,dy);
00944     }
00945   }
00946 }
00947 
00948 
00949 void G4OpenGLViewer::rotateSceneToggle(G4double dx, G4double dy)
00950 {
00951   if (fVP.GetRotationStyle() != G4ViewParameters::freeRotation) {
00952     rotateSceneInViewDirection(dx,dy);
00953   } else {
00954     if( dx != 0) {
00955       rotateSceneThetaPhi(dx,0);
00956     }
00957     if( dy != 0) {
00958       rotateSceneThetaPhi(0,dy);
00959     }
00960   }
00961 }
00962 
00963 void G4OpenGLViewer::rotateSceneThetaPhi(G4double dx, G4double dy)
00964 {
00965   if (!fSceneHandler.GetScene()) {
00966     return;
00967   }
00968 
00969   G4Vector3D vp;
00970   G4Vector3D up;
00971   
00972   G4Vector3D xprime;
00973   G4Vector3D yprime;
00974   G4Vector3D zprime;
00975   
00976   G4double delta_alpha;
00977   G4double delta_theta;
00978   
00979   G4Vector3D new_vp;
00980   G4Vector3D new_up;
00981   
00982   G4double cosalpha;
00983   G4double sinalpha;
00984   
00985   G4Vector3D a1;
00986   G4Vector3D a2;
00987   G4Vector3D delta;
00988   G4Vector3D viewPoint;
00989 
00990     
00991   //phi spin stuff here
00992   
00993   vp = fVP.GetViewpointDirection ().unit ();
00994   up = fVP.GetUpVector ().unit ();
00995   
00996   yprime = (up.cross(vp)).unit();
00997   zprime = (vp.cross(yprime)).unit();
00998   
00999   if (fVP.GetLightsMoveWithCamera()) {
01000     delta_alpha = dy * fRot_sens;
01001     delta_theta = -dx * fRot_sens;
01002   } else {
01003     delta_alpha = -dy * fRot_sens;
01004     delta_theta = dx * fRot_sens;
01005   }    
01006   
01007   delta_alpha *= deg;
01008   delta_theta *= deg;
01009   
01010   new_vp = std::cos(delta_alpha) * vp + std::sin(delta_alpha) * zprime;
01011   
01012   // to avoid z rotation flipping
01013   // to allow more than 360° rotation
01014 
01015   if (fVP.GetLightsMoveWithCamera()) {
01016     new_up = (new_vp.cross(yprime)).unit();
01017     if (new_vp.z()*vp.z() <0) {
01018       new_up.set(new_up.x(),-new_up.y(),new_up.z());
01019     }
01020   } else {
01021     new_up = up;
01022     if (new_vp.z()*vp.z() <0) {
01023       new_up.set(new_up.x(),-new_up.y(),new_up.z());
01024     }
01025   }
01026   fVP.SetUpVector(new_up);
01028   // Rotates by fixed azimuthal angle delta_theta.
01029   
01030   cosalpha = new_up.dot (new_vp.unit());
01031   sinalpha = std::sqrt (1. - std::pow (cosalpha, 2));
01032   yprime = (new_up.cross (new_vp.unit())).unit ();
01033   xprime = yprime.cross (new_up);
01034   // Projection of vp on plane perpendicular to up...
01035   a1 = sinalpha * xprime;
01036   // Required new projection...
01037   a2 = sinalpha * (std::cos (delta_theta) * xprime + std::sin (delta_theta) * yprime);
01038   // Required Increment vector...
01039   delta = a2 - a1;
01040   // So new viewpoint is...
01041   viewPoint = new_vp.unit() + delta;
01042   
01043   fVP.SetViewAndLights (viewPoint);
01044 }
01045 
01046 
01047 void G4OpenGLViewer::rotateSceneInViewDirection(G4double dx, G4double dy)
01048 {
01049   if (!fSceneHandler.GetScene()) {
01050     return;
01051   }
01052 
01053   G4Vector3D vp;
01054   G4Vector3D up;
01055   
01056   G4Vector3D xprime;
01057   G4Vector3D yprime;
01058   G4Vector3D zprime;
01059   
01060   G4Vector3D new_vp;
01061   G4Vector3D new_up;
01062   
01063   G4Vector3D a1;
01064   G4Vector3D a2;
01065   G4Vector3D delta;
01066   G4Vector3D viewPoint;
01067 
01068   dx = dx/100;
01069   dy = dy/100;
01070 
01071   //phi spin stuff here
01072   
01073 #ifdef G4DEBUG_VIS_OGL
01074   printf("G4OpenGLViewer::rotateScene dx:%f dy:%f delta:%f\n",dx,dy, fRot_sens);
01075 #endif
01076 
01077   vp = fVP.GetViewpointDirection ().unit();
01078   up = fVP.GetUpVector ().unit();
01079 
01080   G4Vector3D zPrimeVector = G4Vector3D(up.y()*vp.z()-up.z()*vp.y(),
01081                              up.z()*vp.x()-up.x()*vp.z(),
01082                              up.x()*vp.y()-up.y()*vp.x());
01083 
01084   viewPoint = vp/fRot_sens + (zPrimeVector*dx - up*dy) ;
01085   new_up = G4Vector3D(viewPoint.y()*zPrimeVector.z()-viewPoint.z()*zPrimeVector.y(),
01086                        viewPoint.z()*zPrimeVector.x()-viewPoint.x()*zPrimeVector.z(),
01087                        viewPoint.x()*zPrimeVector.y()-viewPoint.y()*zPrimeVector.x());
01088 
01089   G4Vector3D new_upUnit = new_up.unit();
01090   
01091   
01092 
01093    fVP.SetUpVector(new_upUnit);
01094    fVP.SetViewAndLights (viewPoint);
01095 }
01096 
01097 
01098 #endif

Generated on Mon May 27 17:49:11 2013 for Geant4 by  doxygen 1.4.7