Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

TridGLFrame.cxx

Go to the documentation of this file.
00001 
00002 #include "TridGLFrame.h"
00003 #include "TridPage.h"
00004 #include "TridSketches.h"
00005 #include "TridOpenGLGlobal.h"
00006 #include "TridControl.h"
00007 #include "MessageService/MsgService.h"
00008 
00009 #include "TROOT.h"
00010 #include "TSystem.h"
00011 #include "TGX11.h"
00012 #include "TVirtualX.h"
00013 #include "KeySymbols.h"
00014 
00015 #include <GL/gl.h>
00016 #include <GL/glx.h>
00017 #include <GL/glu.h>
00018 #include "glf.h"
00019 #include <iostream>
00020 #include <sys/time.h>
00021 #include <string>
00022 #include <cmath>
00023 
00024 #ifdef USE_ASIMAGE
00025 extern "C" {
00026   // do this to force code for ISO compliance:
00027 #undef __GNUC__
00028 #undef DEBUG
00029 #undef LOCAL_DEBUG
00030 #undef DEBUG_ALL
00031 #   include "afterbase.h"
00032 #   include "afterimage.h"
00033 }
00034 #endif
00035 
00036 using namespace std;
00037 
00038 CVSID("$Id: TridGLFrame.cxx,v 1.31 2007/09/14 14:12:19 tagg Exp $");
00039 
00043 
00044 class TridGLFrameWindowHandler : public TGUnknownWindowHandler 
00045 {
00046 public:
00047   TridGLFrame* fGLFrame;
00048   Window       fWindow;
00049   TridGLFrameWindowHandler( TridGLFrame* glframe, Window whichWindow) 
00050   {
00051     fGLFrame = glframe;
00052     fWindow = whichWindow;
00053   };
00054   virtual ~TridGLFrameWindowHandler() {};
00055   
00056   virtual Bool_t HandleEvent(Event_t *event)
00057   {
00058     if((Window)(event->fWindow) == fWindow) {      
00059       return fGLFrame->HandleEvent(event);
00060     }    
00061     return false;
00062   }
00063 
00064 private:
00065   TridGLFrameWindowHandler() {};
00066 }; 
00067 
00068 
00072 
00073 TridGLFrame::TridGLFrame(TridPage* tp, TGWindow& parent, TridControl* tc,
00074                          const TridPOV& min,
00075                          const TridPOV& max )
00076   : TGFrame(&parent, 400, 300),
00077     fTridControl(tc),
00078     fAnimTimeMin(-1e99), fAnimTimeMax(1e99) // Default animation time.
00079 {
00080   fTridPage = tp;
00081   fMainFrame = dynamic_cast<const TGMainFrame*>(GetMainFrame());
00082 
00083   gVirtualX->GrabButton(fId, kAnyButton, kAnyModifier,
00084                         kButtonPressMask | kButtonReleaseMask,
00085                         kNone, kNone);
00086   
00087   gVirtualX->SelectInput(fId, kKeyPressMask | kExposureMask | kPointerMotionMask |
00088                          kStructureNotifyMask);
00089 
00090 
00091   fDrawContext = NULL;
00092  
00093   Resize(GetDefaultSize());
00094   fWidth = GetWidth();
00095   fHeight = GetHeight();
00096   fAspectRatio = double(fWidth)/double(fHeight);
00097   MSG("TriD",Msg::kDebug)  << "Initial GLFrame size: " << fWidth << "   " << fHeight << endl;
00098   Layout();
00099 
00100   DeleteSketches();
00101 
00102   // Open the viewport, prepare for stuff.
00103   SetupOpenGL();
00104 
00105   // Set current Point of View to default (probably will be overriden.)
00106   SetPOV();
00107   
00108   // Set max range for user to move around (set to 'anywhere'):
00109   fPOVMin.Copy(min);
00110   fPOVMax.Copy(max);
00111 
00112   //cout << "Min: " << fPOVMin.AsString() << endl;
00113   //cout << "Max: " << fPOVMax.AsString() << endl;
00114   // State variables
00115   fButton = 0;
00116     
00117   // Do a draw into the view.
00118   Update();  
00119   MSG("TriD",Msg::kDebug) << "TridGLFrame constructor.  Window ID is " << fId << endl;
00120 }
00121 
00122 
00123 
00124 TridGLFrame::~TridGLFrame( void )
00125 {
00126   if(fDrawContext) {
00127     glXDestroyContext(fDrawContext->fDisplay,fDrawContext->fglxContext);
00128     XUnmapWindow(fDrawContext->fDisplay, fDrawContext->fWindow);
00129     XDestroyWindow(fDrawContext->fDisplay, fDrawContext->fWindow);
00130     gClient->RemoveUnknownWindowHandler(fDrawContext->fHandler);
00131     delete fDrawContext->fHandler;
00132     delete fDrawContext;
00133   }
00134   MSG("TriD",Msg::kDebug) << "TridGLFrame destructor." << endl;
00135 }
00136 
00137 void TridGLFrame::SetupOpenGL( void )
00138 {
00139   // Pull in the dynamic library, if neccessary
00140   // and start up GL and GLF:
00141   TridOpenGLGlobal::Instance().GlfLoadFont();
00142 
00143   // Make a new 'hider' object, which simply stores some
00144   // variables that OpenGL and GLX need to set the window up.
00145   fDrawContext = CreateDrawContext();
00146 
00147   glXMakeCurrent(fDrawContext->fDisplay, fDrawContext->fWindow, fDrawContext->fglxContext); 
00148   
00149   // Set up the view.
00150   glMatrixMode(GL_PROJECTION);
00151   glLoadIdentity();
00152   SetupProjection();
00153 }
00154 
00155 TridGLFrame::DrawContext* TridGLFrame::CreateDrawContext(Int_t x, Int_t y, Int_t width, Int_t height)
00156 {
00157   if(width  <0 ) width  = fWidth;
00158   if(height <0 ) height = fHeight;
00159 
00160 
00161     // Make a new 'hider' object, which simply stores some
00162   // variables that OpenGL and GLX need to set the window up.
00163   DrawContext* dc = new DrawContext;
00164 
00165   dc->fX = x;
00166   dc->fY = y;
00167   dc->fWidth  = width;
00168   dc->fHeight = height;
00169   
00170   // X11 code to initialize GL
00171   dc->fDisplay = (Display *) gVirtualX->GetDisplay();
00172   
00173   static int dblBuf[] = {
00174     GLX_DOUBLEBUFFER,
00175     GLX_RGBA, GLX_DEPTH_SIZE, 16,
00176     GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
00177     None
00178   };
00179   static int *snglBuf = &dblBuf[1];
00180   
00181   dc->fxVisInfo = glXChooseVisual(dc->fDisplay, DefaultScreen(dc->fDisplay), dblBuf);
00182   if (dc->fxVisInfo == 0)
00183     dc->fxVisInfo = glXChooseVisual(dc->fDisplay, DefaultScreen(dc->fDisplay), snglBuf);  
00184   
00185   if (dc->fxVisInfo == 0)
00186     MSG("TriD",Msg::kDebug) << "InitGLWindow: Error! Barf! No good visual" << endl;
00187   
00188   // Create OpenGL context.
00189   dc->fglxContext = glXCreateContext(dc->fDisplay, dc->fxVisInfo, None, GL_TRUE);    
00190   if(dc->fglxContext == 0) {
00191     MSG("TriD",Msg::kInfo) << "OpenGL: DRI unavailable; using indirect renderinging." << endl;
00192     dc->fglxContext = glXCreateContext(dc->fDisplay, dc->fxVisInfo, None, GL_FALSE);    // Set last parameter to false for indirect rendering.
00193   }
00194 
00195   
00196   // Create a window.
00197   int xval, yval;
00198   unsigned int wval, hval, border, depth;
00199   Window root, wind = (Window) GetId();
00200   XGetGeometry(dc->fDisplay, wind, &root, &xval, &yval, &wval, &hval, &border, &depth); 
00201   
00202   // window attributes
00203   ULong_t mask;
00204   XSetWindowAttributes attr; 
00205   
00206   attr.background_pixel = 0;
00207   attr.border_pixel = 0;
00208   attr.colormap = XCreateColormap(dc->fDisplay, root, dc->fxVisInfo->visual, AllocNone);
00209   attr.event_mask = NoEventMask;
00210   attr.backing_store = Always;
00211   attr.bit_gravity = NorthWestGravity;
00212   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask |
00213     CWBackingStore | CWBitGravity;
00214   
00215   dc->fWindow = XCreateWindow(dc->fDisplay, wind, 
00216                               xval + x, yval + y, width, height,
00217                               0, dc->fxVisInfo->depth, InputOutput,
00218                               dc->fxVisInfo->visual, mask, &attr);
00219   
00220   XMapWindow(dc->fDisplay, dc->fWindow);
00221 
00222   // Tell ROOT how to handle events for this window.
00223   MSG("TriD",Msg::kDebug) << "GL window is " << dc->fWindow << endl;
00224   dc->fHandler = new TridGLFrameWindowHandler(this,dc->fWindow);
00225   gClient->AddUnknownWindowHandler(dc->fHandler);
00226   
00227   // Make sure expose events get to it. (Only trap expose events; we want everything else
00228   // to go to the fGLFrame that contains it. Far simpler that way.
00229   XSelectInput(dc->fDisplay, dc->fWindow, ExposureMask );
00230   glXMakeCurrent(dc->fDisplay, dc->fWindow, dc->fglxContext); 
00231 
00232   //ResizeViewport();
00233 
00234   return dc;
00235 }
00236 
00237 
00238 Bool_t TridGLFrame::HandleMotion( int button, int startx, int starty, int stopx, int stopy )
00239 {
00240   int delx, dely;
00241   delx = stopx-startx;
00242   dely = stopy-starty;
00243   
00244   
00245   if(fButton == 0 ) {
00246     // The mouse is travelling.. pick and show.
00247     UInt_t name = Pick(stopx,stopy);
00248     if(name!=fPicked) {
00249       fPicked = name;
00250       fTridPage->MouseOver(fPicked);
00251       Update();
00252       return true;
00253       }
00254   } else if( button == kButton1 ) {
00255     // Rotate.
00256     if(abs(delx) + abs(dely)>0){
00257       fPOV.fPhi   += ((float)delx)/((float)fDrawContext->fWidth)*400.;
00258       fPOV.fTheta += ((float)dely)/((float)fDrawContext->fHeight)*400.;
00259       fPOV.Push();
00260       Update();      
00261       return true;
00262     }
00263   } else if( button == kButton2 ) {
00264     // Scale.  Towards center means shrink, away from center means grow.
00265     if(abs(delx) + abs(dely)>0){
00266       float sdx = (float)(startx - (fDrawContext->fWidth/2.));
00267       float sdy = (float)(starty - (fDrawContext->fHeight/2.));
00268       float dot = sdx*delx + sdy*dely;
00269       dot = dot/sqrt(sdy*sdy+sdx*sdx);
00270       
00271       fPOV.fDist -= dot*100/(double)(fDrawContext->fWidth);
00272       fPOV.PushIfChanged();
00273       Update();
00274       return true;
00275     }
00276   } else if( button == kButton3 ) {
00277     // Slide.
00278     if(abs(delx) + abs(dely)>0){
00279       // This mostly does what I want. Still some problems; must go back
00280       // when I understand the math a little better.
00281       GLfloat z;
00282       GLdouble x1, y1, z1;
00283       GLdouble x2, y2, z2;
00284       GLdouble  model[16];
00285       GLdouble  proj[16];
00286       GLint     view[4];
00287       glGetDoublev(GL_MODELVIEW_MATRIX, model);
00288       glGetDoublev(GL_PROJECTION_MATRIX, proj);
00289       glGetIntegerv(GL_VIEWPORT, view); 
00290       
00291       glReadPixels(startx, fHeight-starty, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);
00292       gluUnProject(startx, fHeight-starty,  z, model, proj, view, &x1, &y1, &z1);
00293       gluUnProject(stopx,  fHeight-stopy,       z, model, proj, view, &x2, &y2, &z2);
00294 
00295       MSG("TriD",Msg::kDebug) << "Panning. ReadPixel z is " << z << endl;
00296       
00297       // NB all plotting is in x-z plane now.
00298       fPOV.fx -= x2-x1;
00299       fPOV.fy -= y2-y1;
00300       fPOV.fz -= z2-z1;
00301       
00302       fPOV.Push();
00303       Update();
00304       return true;
00305     }
00306   }
00307   return true;
00308 }
00309 
00310 
00311 Bool_t TridGLFrame::HandleMotion(Event_t* ev)
00312 {
00313   HandleMotion(fButton, fMouseLast_x, fMouseLast_y, ev->fX, ev->fY );
00314 
00315   fButtonTraveled += abs(ev->fX - fMouseLast_x) + abs(ev->fY - fMouseLast_y);
00316 
00317   fMouseLast_x = ev->fX;
00318   fMouseLast_y = ev->fY;
00319 
00320   return true;
00321 }
00322 
00323 Bool_t TridGLFrame::HandleButton(Event_t *ev)
00324 {
00325   
00326   if((ev->fCode == kButton1) || (ev->fCode == kButton2) || (ev->fCode == kButton3) ){
00327     if (ev->fType == kButtonPress) {
00328       fMouseLast_x = fMouseStart_x = ev->fX;
00329       fMouseLast_y = fMouseStart_y = ev->fY;
00330       fButtonTraveled = 0;
00331       fButton = ev->fCode;  // Note: ignores possible mulitple-presses.
00332     }
00333     else if (ev->fType == kButtonRelease) {
00334       if((fButtonTraveled<5)&&(fButton==kButton1)) {
00335         // This was a click-and-relase. Select.
00336         UInt_t name = Pick(fMouseStart_x,fMouseStart_y);
00337         if(name>0) fTridPage->MouseClick(name);
00338       } else {
00339         // It was not a click, but a drag.
00340         fPOV.PushIfChanged();
00341       }
00342       fButton = 0;
00343     }
00344   }
00345   
00346   else if(ev->fCode == kButton4) {
00347     if (ev->fType == kButtonPress) {
00348       // Zoom in.
00349       fPOV.fDist -=1; fPOV.PushIfChanged();
00350       Update();
00351     }
00352   }
00353   else if(ev->fCode == kButton5) {
00354     if (ev->fType == kButtonPress) {    
00355       // Zoom out.
00356       fPOV.fDist     +=1; fPOV.PushIfChanged();
00357       Update();
00358     }
00359   }
00360   
00361   //cout << "Got button" << endl;
00362   return true;
00363 }
00364 
00365 Bool_t TridGLFrame::HandleKey(Event_t *ev)
00366 {
00367   if (ev->fType == kGKeyPress) {
00368     UInt_t keysym;
00369     char str[2];
00370     gVirtualX->LookupString(ev,(char*)str,sizeof(str),keysym);
00371     switch((EKeySym)keysym) {
00372     case kKey_q:
00373       fPOV.fz +=0.1;  
00374       break;
00375     case  kKey_a:
00376       fPOV.fz -=0.1;  
00377       break;
00378     case kKey_w:
00379       fPOV.fy +=0.1;  
00380       break;
00381     case  kKey_s:
00382       fPOV.fy-= 0.1;  
00383       break;
00384     case kKey_e:
00385       fPOV.fx+= 0.1;  
00386       break;
00387     case kKey_d:
00388       fPOV.fx-= 0.1;  
00389       break;
00390     case kKey_Up:
00391       // Zoom in.
00392       fPOV.fDist    -= 1;  
00393       break;
00394     case kKey_Down:
00395       // Zoom out
00396       fPOV.fDist    += 1;  
00397       break;
00398     case kKey_Left:
00399       fPOV.fPhi += 1;  
00400       break;
00401     case kKey_Right:
00402       fPOV.fPhi -= 1;  
00403       break;      
00404     default:
00405       break;
00406     }
00407   }
00408 
00409   fPOV.PushIfChanged();
00410   Update();
00411   return true;
00412 }
00413 
00414 Bool_t TridGLFrame::HandleContainerExpose(Event_t *ev)
00415 {
00416    // Handle expose events.
00417   //cout << "Expose event (container)." << endl;
00418   if (ev->fCount == 0)
00419     Update();
00420   
00421   return kTRUE;
00422 }
00423 
00424 Bool_t TridGLFrame::HandleExpose(Event_t *ev)
00425 {
00426    // Handle expose events.
00427   //cout << "Expose event." << endl;
00428   if (ev->fCount == 0)
00429     Update();
00430   
00431   return kTRUE;
00432 }
00433  
00434 Bool_t TridGLFrame::HandleConfigureNotify(Event_t* ev)
00435 {
00436   // Handle configure (i.e. resize) event.
00437   fDrawContext->fWidth   = fWidth  = ev->fWidth;
00438   fDrawContext->fHeight  = fHeight = ev->fHeight;
00439   fAspectRatio = double(fWidth)/double(fHeight);
00440   Layout();
00441   ResizeViewport();
00442   Update();  
00443   return kTRUE;
00444 }
00445 
00446 void TridGLFrame::ResizeViewport()
00447 {
00448   int xval, yval;
00449   unsigned int wval, hval, border, depth;
00450   Window root, wind = (Window) GetId();
00451   XGetGeometry(fDrawContext->fDisplay, wind, &root, &xval, &yval, &wval, &hval, &border, &depth); 
00452   XMoveWindow(fDrawContext->fDisplay, fDrawContext->fWindow, xval + fDrawContext->fX, yval + fDrawContext->fY);
00453   
00454   XResizeWindow(fDrawContext->fDisplay, fDrawContext->fWindow, fDrawContext->fWidth, fDrawContext->fHeight);
00455   glXMakeCurrent(fDrawContext->fDisplay, fDrawContext->fWindow, fDrawContext->fglxContext);
00456   glViewport(0, 0, (GLint) fDrawContext->fWidth, (GLint) fDrawContext->fHeight);
00457   
00458   // Set up the view.
00459   glMatrixMode (GL_PROJECTION);
00460   glLoadIdentity ();
00461   SetupProjection();
00462 }
00463 
00464 
00468 
00469 unsigned int TridGLFrame::Pick( int x, int y )
00470 {
00471   const int BUFSIZE =512;
00472   static GLuint selectBuf[BUFSIZE];
00473   GLint hits;
00474   GLint viewport[4];  
00475 
00476   glXMakeCurrent(fDrawContext->fDisplay, fDrawContext->fWindow, fDrawContext->fglxContext);
00477 
00478   // Get viewport coordinates (safest way of knowing width, height)
00479   glGetIntegerv (GL_VIEWPORT, viewport);
00480   
00481   // Give opengl selectBuf as the place to store hits.
00482   glSelectBuffer (BUFSIZE, selectBuf);
00483 
00484   // Tell OpenGL not to render, only to think about drawing.
00485   glRenderMode (GL_SELECT);
00486 
00487   // Make sure we're using names, set default to 0.
00488   glInitNames();
00489   glPushName(0);
00490   
00491   // This mimics the Update() command, but doesn't touch the screen.
00492 
00493   // Don't SetupProjection(), but instead do:
00494   glMatrixMode (GL_PROJECTION);
00495   glPushMatrix ();    // Push old projection onto stack.
00496   glLoadIdentity ();  
00497   //  create 5x5 pixel picking region near cursor location     
00498   gluPickMatrix ((GLdouble) x, (GLdouble) (viewport[3] - y),
00499                  4.0, 4.0, viewport);
00500   SetupProjection();  // Add in our custom projection.
00501   TransformToPOV();   // Set up coords
00502   DrawObjects();      // Draw stuff into the scene (Not the HUD or suchlike)
00503   
00504   // Now pop the matrix.
00505   glMatrixMode(GL_PROJECTION);
00506   glPopMatrix();
00507 
00508   // Do it! (I don't know which of these does it.)
00509   glFlush();
00510   hits = glRenderMode(GL_RENDER);
00511 
00512   // We have the hits.. now process to find the best (i.e. topmost) hit.
00513   GLuint* ptr = (GLuint *) selectBuf;
00514   unsigned int bestName = 0;
00515   float bestZ = 99;
00516 
00517   for(int i=0;i<hits;i++) {
00518     unsigned int numNames = *ptr; // Number of names for this hit.
00519     ptr++;
00520     float z1 = float(*(ptr))/0x7fffffff;
00521     ptr++;
00522     float z2 = float(*(ptr))/0x7fffffff;
00523     ptr++;
00524     for(unsigned int j=0; j<numNames; j++) {
00525       unsigned int name = *ptr;
00526       ptr++;
00527       if(((z1+z2)<bestZ) && (name>0)) { bestName = name; bestZ = z1+z2; };
00528     }
00529   }
00530   return bestName;
00531 }
00532 
00533 
00534 
00535 
00539 
00540 void TridGLFrame::Update( void )
00541 {
00542   // Clears and redraws the OpenGL viewport.
00543 
00544   struct timeval timestart,timeend;
00545   gettimeofday(&timestart,0);
00546 
00547   // Unsure that our window is the current one for OpenGL.
00548   // (This call must be atomic!)
00549   glXMakeCurrent(fDrawContext->fDisplay, fDrawContext->fWindow, fDrawContext->fglxContext);
00550   
00551   // Draw operations.
00552   ClearViewport();      // Wipe blank. (Could be later, but we are double-buffering.)
00553   TransformToPOV();     // Set the cmera in world coordinates
00554   SetupOptions();       // Change OpenGL options
00555   SetupLighting();      // Put in light sources
00556   DrawObjects();        // Draw the Sketches
00557   DrawHUD(fHUDText.c_str());            // Put on the overlay.
00558 
00559   glFlush();            // Send commands to X server
00560   SwapBuffers();        // Swap the buffers to display it, if supported.
00561 
00562   gettimeofday(&timeend,0);
00563   
00564   fFrameTime = (timeend.tv_sec - timestart.tv_sec) +
00565     (timeend.tv_usec - timestart.tv_usec) * 0.000001;
00566 }
00567 
00568 void TridGLFrame::SetupProjection( void )
00569 {
00570   gluPerspective(30.0f,(GLfloat)fDrawContext->fWidth/(GLfloat)fDrawContext->fHeight,0.1f,100.0f);
00571 }
00572 
00573 void TridGLFrame::ClearViewport()
00574 {
00575   TVector3 bg = fTridControl->GetBackgroundColor();
00576   glClearColor(bg.x(),bg.y(),bg.y(),0.0);
00577   glClearDepth(1.0);
00578   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00579 }
00580 
00581 void TridGLFrame::TransformToPOV( void )
00582 {
00583   // Clip the POV so it conforms to limits.
00584   NormalizeAndClipPOV();
00585 
00586    // Need to manipulate the ModelView matrix to move our model around.
00587   glMatrixMode(GL_MODELVIEW);
00588   
00589   // Reset to 0,0,0; no rotation, no scaling.
00590   glLoadIdentity(); 
00591   
00592   // Pull back so we can look at it.
00593   glTranslatef(0.0f,0.0f,-fPOV.GetDist());
00594     
00595   // Rotate to our view.
00596   glRotatef(fPOV.GetTheta(),1.0f,0.0f,0.0f); // Rotate to elevation.
00597   if(fPOV.GetPhi()!=0)
00598     glRotatef(fPOV.GetPhi()  ,0.0f,1.0f,0.0f); // Rotate to side
00599   
00600   // Move to our viewpoint.
00601   glTranslatef(-fPOV.GetX(), -fPOV.GetY(), -fPOV.GetZ());  // Move to our viewpoint.
00602 }
00603 
00604 void TridGLFrame::SetupOptions( ) 
00605 {
00606   // Enables Smooth Color Shading; try GL_FLAT for (lack of) fun.
00607   glShadeModel(GL_SMOOTH);
00608   glEnable(GL_DEPTH_TEST); // Disable depth test if blending
00609   // Allow antialiasing.
00610   glEnable(GL_LINE_SMOOTH);
00611   glHint (GL_LINE_SMOOTH_HINT, GL_DONT_CARE);
00612 }
00613 
00614 void TridGLFrame::SetupLighting( Bool_t lighting_on )
00615 {
00616   lighting_on = false;
00617   if(!lighting_on) {
00618     glDisable(GL_LIGHTING);
00619     glEnable(GL_COLOR_MATERIAL);
00620   } else {
00621     // A handy trick -- have surface material mirror the color.
00622     //glColorMaterial(GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
00623     glEnable(GL_COLOR_MATERIAL);  
00624     
00625     glEnable(GL_LIGHTING);
00626     
00627     // Set up a light, turn it on.
00628     // Settings for our light.  Try playing with these (or add more lights).
00629     
00630     float Light_Ambient0[]=  { 0.3f, 0.3f, 0.3f, 1.0f };
00631     float Light_Diffuse0[]=  { 1.2f, 1.2f, 1.2f, 1.0f }; 
00632     float Light_Position0[]= { 0.0f, 8.0f, 12.0f, 1.0f };
00633     glLightfv(GL_LIGHT0, GL_POSITION, Light_Position0);
00634     glLightfv(GL_LIGHT0, GL_AMBIENT,  Light_Ambient0);
00635     glLightfv(GL_LIGHT0, GL_DIFFUSE,  Light_Diffuse0); 
00636     glEnable (GL_LIGHT0); 
00637     
00638     
00639     float Light_Ambient1[]=  { 0.3f, 0.3f, 0.3f, 1.0f };
00640     float Light_Diffuse1[]=  { 1.2f, 1.2f, 1.2f, 1.0f }; 
00641     float Light_Position1[]= { 0.0f, 8.0f, 0.0f, 1.0f };
00642     glLightfv(GL_LIGHT1, GL_POSITION, Light_Position1);
00643     glLightfv(GL_LIGHT1, GL_AMBIENT,  Light_Ambient1);
00644     glLightfv(GL_LIGHT1, GL_DIFFUSE,  Light_Diffuse1); 
00645     glEnable (GL_LIGHT1); 
00646   }
00647 } 
00648 
00649 
00650 void TridGLFrame::DrawObjects(  )
00651 {
00652   glMatrixMode(GL_MODELVIEW); 
00653   TridSketchListItr itr = GetIterator();
00654   TridSketch* sketch;
00655   fNumSketches = 0;
00656   fNumSketchesDrawn = 0;
00657 
00658   const double opaque_thresh = 0.99;
00659 
00660   // Draw opaque objects first.
00661   itr.Reset();
00662   while( (sketch = itr.Next()) ){
00663     fNumSketches++;
00664     if(sketch->GetTransparency()>=opaque_thresh) {
00665       Bool_t drawn = sketch->Draw(fAnimTimeMin, fAnimTimeMax);
00666       if(drawn) fNumSketchesDrawn++;
00667     }
00668   }
00669 
00670   // Next, compute z-ordered list, and draw them in order.
00671   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00672   glEnable(GL_BLEND);
00673   glDepthMask(GL_FALSE);
00674 
00675   std::map<double,TridSketch*>           sortedSketches;
00676   std::map<double,TridSketch*>::iterator sortItr;
00677 
00678   double modelViewMatrix[16];
00679   glGetDoublev(GL_MODELVIEW_MATRIX, modelViewMatrix);
00680 
00681   itr.Reset();
00682   while( (sketch = itr.Next()) ){
00683     if(sketch->GetTransparency()<opaque_thresh) {
00684       double z = sketch->ComputeApparentZ(modelViewMatrix);
00685       sortedSketches[z]=sketch;
00686     }
00687   }
00688   
00689   for(sortItr = sortedSketches.begin(); sortItr!=sortedSketches.end(); sortItr++) 
00690     {
00691       sketch = sortItr->second;
00692       Bool_t drawn = sketch->Draw(fAnimTimeMin, fAnimTimeMax);
00693       if(drawn) fNumSketchesDrawn++;      
00694     }
00695 
00696   glDepthMask(GL_TRUE);
00697 
00698 }
00699  
00700 
00701 void TridGLFrame::DrawHUD( const char* text )
00702 { 
00703   //
00704   // Draws the 'heads up display'; overlay onto the 3d view, such as
00705   // feedback or controls.
00706   //
00707 
00708   // Custom coordinate system:
00709   // new coord system: left side is -1, right side is +1, aspect ratio 
00710   // determines height.
00711   glMatrixMode(GL_PROJECTION);
00712   glPushMatrix();
00713   glLoadIdentity();
00714   
00715   float yHeight = 1;
00716   if(fWidth>0) yHeight = (float)fHeight/(float)fWidth;
00717   gluOrtho2D(-1.0,1.0,-yHeight,yHeight);
00718 
00719   glMatrixMode(GL_MODELVIEW);
00720   glPushMatrix();
00721   glLoadIdentity();
00722   glTranslatef(-0.99,-yHeight+0.02,0);
00723 
00724   
00725   
00726   glDisable(GL_TEXTURE_2D);
00727   glDisable(GL_LIGHTING);
00728   glDisable(GL_DEPTH_TEST);
00729   
00730    glLoadName(0);
00731    glfStringCentering(GL_FALSE);
00732    glfSetRotateAngle(0.0f);
00733    glfStringDirection(GL_LEFT);
00734 
00735    glScalef(0.02,0.02,0.01);
00736 
00737    char buff[500];
00738    if(strlen(text)==0) {
00739      glColor4f(1.0f, 0.2f, 0.2f, 0.75f);
00740      sprintf(buff," (%3.1f,%3.1f,%4.1f) D:%4.1f Th:%3f Phi:%3f  Pick: %d  Render: %fs  Objects: %d/%d",
00741              fPOV.GetX(),fPOV.GetY(),fPOV.GetZ(),
00742              fPOV.GetDist(),fPOV.GetTheta(),fPOV.GetPhi(),fPicked,
00743              fFrameTime,
00744            fNumSketchesDrawn,fNumSketches);
00745    } else {
00746      glColor4f(1.0f, 0.9f, 0.9f, 0.75f);
00747      strncpy(buff,text,500);
00748    }
00749    glfDrawSolidString(buff);
00750 
00751    glMatrixMode(GL_MODELVIEW);
00752    glPopMatrix();
00753    glMatrixMode(GL_PROJECTION);
00754    glPopMatrix();
00755    
00756 }
00757 
00758 void TridGLFrame::SwapBuffers()
00759 {
00760    // Swap two GL buffers.
00761  
00762    glXSwapBuffers(fDrawContext->fDisplay, fDrawContext->fWindow);   
00763    if (!glXIsDirect(fDrawContext->fDisplay, fDrawContext->fglxContext)) {
00764       glFinish();
00765    }
00766  
00767    // for help debugging, report any OpenGL errors that occur per frame
00768    GLenum error;
00769    while ((error = glGetError()) != GL_NO_ERROR)  cerr << "SwapBuffers error. GL error: " <<gluErrorString(error) << endl;
00770 }
00771 
00772 
00773 void TridGLFrame::SetPOV( float x, float y, float z, float distance, float theta, float phi)
00774 {
00775   // Sets the Point of View.0  // x,y,z: Coordinates of place to look at
00776   // distance: How far away from the point we are.
00777   // theta: elevation above or below the horizontal (degrees)
00778   // phi: rotation around the detector (degrees)
00779   fPOV.Set(x,y,z,distance,theta,phi);
00780   fPOV.Push();
00781 }
00782 
00783 void TridGLFrame::SetPOV( const TridPOV& in )
00784 {
00785   // Sets the Point of View.0  // x,y,z: Coordinates of place to look at
00786   // distance: How far away from the point we are.
00787   // theta: elevation above or below the horizontal (degrees)
00788   // phi: rotation around the detector (degrees)
00789   fPOV.Copy(in);
00790   fPOV.Push();
00791 }
00792 
00793 void TridGLFrame::SetMinPOV( const TridPOV& in )
00794 {
00795   fPOVMin.Copy(in);
00796 }
00797 
00798 void TridGLFrame::SetMaxPOV( const TridPOV& in )
00799 {
00800   fPOVMin.Copy(in);
00801 }
00802 
00803 void TridGLFrame::NormalizeAndClipPOV( void ) 
00804 {
00805   // Normalize the Phi coordinate.
00806   fPOV.fPhi = fmod(fPOV.fPhi+540.,360) - 180;
00807 
00808   if(fPOV.fx < fPOVMin.fx) fPOV.fx = fPOVMin.fx;
00809   if(fPOV.fy < fPOVMin.fy) fPOV.fy = fPOVMin.fy;
00810   if(fPOV.fz < fPOVMin.fz) fPOV.fz = fPOVMin.fz;
00811   if(fPOV.fDist  < fPOVMin.fDist)  fPOV.fDist  = fPOVMin.fDist;
00812   if(fPOV.fTheta < fPOVMin.fTheta) fPOV.fTheta = fPOVMin.fTheta;
00813   if(fPOV.fPhi   < fPOVMin.fPhi)   fPOV.fPhi   = fPOVMin.fPhi;
00814 
00815   if(fPOV.fx > fPOVMax.fx) fPOV.fx = fPOVMax.fx;
00816   if(fPOV.fy > fPOVMax.fy) fPOV.fy = fPOVMax.fy;
00817   if(fPOV.fz > fPOVMax.fz) fPOV.fz = fPOVMax.fz;
00818   if(fPOV.fDist  > fPOVMax.fDist) fPOV.fDist = fPOVMax.fDist;
00819   if(fPOV.fTheta > fPOVMax.fTheta) fPOV.fTheta = fPOVMax.fTheta;
00820   if(fPOV.fPhi   > fPOVMax.fPhi)   fPOV.fPhi   = fPOVMax.fPhi;  
00821 }
00822 
00823 
00824 void TridGLFrame::Print(const char* filename, const char* text)
00825 {
00826   // Draw this frame into a file.
00827   
00828 #ifdef USE_RAWDUMP
00829   // This version of the code uses a raw OpenGL dump of the backing store.
00830   // This works on the Mac OSX platform, and is probably the least platform-dependent
00831   // version of all the codes.
00832 
00833   // Unsure that our window is the current one for OpenGL.
00834   // (This call must be atomic!)
00835   glXMakeCurrent(fDrawContext->fDisplay, fDrawContext->fWindow, fDrawContext->fglxContext);
00836   // Do everything but swap buffers.
00837   ClearViewport();      // Wipe blank. (Could be later, but we are double-buffering.)
00838   TransformToPOV();     // Set the cmera in world coordinates
00839   SetupOptions();       // Change OpenGL options
00840   SetupLighting();      // Put in light sources
00841   DrawObjects();        // Draw the Sketches
00842   DrawHUD(text);        // User text.
00843   glFlush();            // Send commands to X server
00844   
00845   std::string rawfile = filename;
00846   rawfile += ".raw";
00847   RawDump(rawfile.c_str());
00848 
00849   const char* cmd = Form("convert -depth 8 -size %dx%d rgb:%s %s",
00850                          fWidth, fHeight,
00851                          rawfile.c_str(), filename);
00852   int retval = gSystem->Exec(cmd);
00853   if(retval) {
00854     MSG("TriD",Msg::kWarning) << "'convert' command failed. Raw file dumped: " << rawfile.c_str() << endl;
00855   } else {
00856     // Delete the temporary file.
00857     gSystem->Unlink(rawfile.c_str());
00858   }
00859   return;
00860 #endif
00861   
00862 
00863 #ifdef USE_ASIMAGE
00864   const char* dir  = gSystem->DirName(filename);
00865   const char* file = gSystem->BaseName(filename);
00866   ASImageFileTypes atype = ASIT_Gif;
00867 
00868   const char* suffix = file + strlen(file) -2;
00869   while(suffix>=file) {
00870     if(suffix[0]=='.') { suffix++; break; }
00871     suffix--;
00872   }
00873 
00874   if(strcmp(suffix,"xpm")==0) atype = ASIT_Xpm;  
00875   if(strcmp(suffix,"png")==0) atype = ASIT_Png;  
00876   if(strcmp(suffix,"jpg")==0) atype = ASIT_Jpeg;
00877   if(strcmp(suffix,"jpeg")==0) atype = ASIT_Jpeg;
00878   if(strcmp(suffix,"gif")==0) atype = ASIT_Gif;  
00879   if(strcmp(suffix,"tiff")==0) atype = ASIT_Tiff;  
00880 
00881 
00882   XImage* ximage = XGetImage(fDrawContext->fDisplay,
00883                              fDrawContext->fWindow,
00884                              fDrawContext->fX,
00885                              fDrawContext->fY,
00886                              fDrawContext->fWidth,
00887                              fDrawContext->fHeight,
00888                              XAllPlanes(), ZPixmap);
00889   if(ximage==NULL) {
00890     MSG("TriD",Msg::kWarning) << "Error in Print() - Couldn't make the XImage! " << endl;
00891     return;
00892   }
00893   
00894   Int_t screen  = gVirtualX->GetScreen();
00895   Int_t depth   = gVirtualX->GetDepth();
00896   Visual *vis   = (Visual*) gVirtualX->GetVisual();
00897   Colormap cmap = (Colormap) gVirtualX->GetColormap();
00898   ASVisual* asv =  create_asvisual_for_id(fDrawContext->fDisplay,
00899                                           screen, depth,
00900                                           XVisualIDFromVisual(vis), 
00901                                           cmap, 0);
00902   if(asv==0) {
00903     MSG("TriD",Msg::kWarning)  << "Couldn't make the ASVisual! " << endl;
00904     return;
00905   }
00906   
00907   ASImage* asimage = ximage2asimage(asv, ximage, 10); // 10 is compression from 0 to 100
00908   if(asimage==0) {
00909     cout << "Couldn't make the ASImage! " << endl;
00910     return;
00911   } 
00912   ASImageExportParams parms;
00913   switch (atype) {
00914   case ASIT_Xpm:
00915     parms.xpm.type = atype;
00916     parms.xpm.flags = EXPORT_ALPHA;
00917     parms.xpm.dither = 4;
00918     parms.xpm.opaque_threshold = 127;
00919     parms.xpm.max_colors = 512;
00920     break;
00921   case ASIT_Png:
00922     parms.png.type = atype;
00923     parms.png.flags = EXPORT_ALPHA;
00924     parms.png.compression = 50;
00925     break;
00926   case ASIT_Jpeg:
00927     parms.jpeg.type = atype;
00928     parms.jpeg.flags = 0;
00929     parms.jpeg.quality = ASIMAGE_QUALITY_GOOD; // also poor, fast, top
00930     break;
00931   case ASIT_Gif:
00932     parms.gif.type = atype;
00933     parms.gif.flags = EXPORT_ALPHA;
00934     parms.gif.dither = 0; 
00935     parms.gif.opaque_threshold = 0;
00936     break;
00937   case ASIT_Tiff:
00938     parms.tiff.type = atype;
00939     parms.tiff.flags = EXPORT_ALPHA;
00940     parms.tiff.rows_per_strip = 0;
00941     parms.tiff.compression_type = TIFF_COMPRESSION_JPEG;
00942     parms.tiff.jpeg_quality = 100;
00943     parms.tiff.opaque_threshold = 0;
00944            break;
00945   default:
00946     return;
00947   }
00948 
00949   if(
00950      ASImage2file( asimage, dir, file,
00951                    atype, &parms )
00952      ) 
00953     MSG("TriD",Msg::kInfo) << "Wrote file " << file << endl;
00954   else 
00955     MSG("TriD",Msg::kWarning) << "Write failed!" << endl;
00956   
00957 
00958   if(asimage) destroy_asimage(&asimage);
00959   if(ximage) XDestroyImage(ximage);
00960 
00961   return;
00962 #endif
00963 
00964 #ifdef USE_WRITEGIF
00965 
00974 
00975   Int_t wid = gVirtualX->OpenPixmap(fWidth,fHeight);
00976   gVirtualX->SelectWindow(wid);
00977   Window_t winid = gVirtualX->GetWindowID(wid);
00978   
00979   static int snglBuf[] = {
00980     GLX_RGBA, GLX_DEPTH_SIZE, 16,
00981     GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1,
00982     None
00983   };
00984   
00985   Display*     display = (Display *) gVirtualX->GetDisplay();
00986   XVisualInfo* xvisinfo = glXChooseVisual(display, DefaultScreen(display), snglBuf);  
00987   
00988   if (xvisinfo == 0)
00989     cout << "InitGLWindow: Error! Barf! No good visual" << endl;
00990   // Create OpenGL context.
00991   GLXContext glxContext = glXCreateContext(display, xvisinfo, None, GL_FALSE);    // Set last parameter to false for indirect rendering.
00992   
00993   GLXPixmap glxPixmap = glXCreateGLXPixmap( display, xvisinfo, (Pixmap) winid);
00994 
00995   glXMakeCurrent(display, glxPixmap, glxContext );
00996   glViewport(0, 0, (GLint) fWidth, (GLint) fHeight);
00997   glMatrixMode(GL_PROJECTION);
00998   glLoadIdentity();
00999   SetupProjection();
01000   
01001   ClearViewport();      // Wipe blank. (Could be later, but we are double-buffering.)
01002   TransformToPOV();
01003 
01004   // Boring, boring, boring!
01005   glShadeModel(GL_FLAT);
01006   glDisable(GL_BLEND);
01007   SetupLighting(false);
01008 
01009   DrawObjects();
01010   glFlush();
01011 
01012   if (gVirtualX->WriteGIF(filename)) {
01013     cout << "Snap taken:" << filename << endl;
01014   } else {
01015     cout << "TVirtualX::WriteGIF() failed!" << endl;
01016   }
01017 
01018   glXDestroyGLXPixmap(display, glxPixmap);
01019   gVirtualX->ClosePixmap();
01020   glXDestroyContext( display, glxContext );
01021 
01022   return;
01023 #endif
01024 
01025 }
01026 
01027 
01028 
01029 int TridGLFrame::RawDump(const char* filename)
01030 {
01031   // 
01032   //    Write the current view to a file.
01033   //    File format will be raw.
01034   // 
01035   
01036    int i,j;
01037    FILE *fptr;
01038    unsigned char *image;
01039 
01040 
01041    /* Allocate our buffer for the image */
01042    if ((image = (unsigned char*) malloc(3*fWidth*fHeight*sizeof(char))) == NULL) {
01043       fprintf(stderr,"Failed to allocate memory for image\n");
01044       return 1;
01045    }
01046 
01047    glPixelStorei(GL_PACK_ALIGNMENT,1);
01048 
01049    /* Open the file */
01050    if ((fptr = fopen(filename,"w")) == NULL) {
01051       fprintf(stderr,"Failed to open file for window dump\n");
01052       return 1;
01053    }
01054 
01055    /* Copy the image into our buffer */
01056    glReadBuffer(GL_BACK_LEFT);
01057    glReadPixels(0,0,fWidth,fHeight,GL_RGB,GL_UNSIGNED_BYTE,image);
01058 
01059    /* Write the raw file */
01060    /* fprintf(fptr,"P6\n%d %d\n255\n",width,height); for ppm */
01061    for (j=fHeight-1;j>=0;j--) {
01062      for (i=0;i<(int)fWidth;i++) {
01063          fputc(image[3*j*fWidth+3*i+0],fptr);
01064          fputc(image[3*j*fWidth+3*i+1],fptr);
01065          fputc(image[3*j*fWidth+3*i+2],fptr);
01066       }
01067    }
01068    fclose(fptr);
01069 
01070    /* Clean up */
01071    free(image);
01072    return 0;
01073 }

Generated on Mon Feb 15 11:07:43 2010 for loon by  doxygen 1.3.9.1