ViewPort3D.C

Go to the documentation of this file.
00001 /*!@file GUI/ViewPort3D.C  3D rendering view port */
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu>
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/GUI/ViewPort3D.C $
00035 // $Id: ViewPort3D.C 14492 2011-02-11 22:53:49Z lior $
00036 //
00037 
00038 
00039 //TODO:
00040 //http://www.opengl.org.ru/docs/pg/0204.html
00041 //void glEdgeFlag(GLboolean flag);
00042 //void glEdgeFlagv(const GLboolean *flag);
00043 //
00044 //Indicates whether a vertex should be considered as initializing a boundary edge of a polygon. If flag is GL_TRUE, the edge flag is set to TRUE (the default), and any vertices created are considered to precede boundary edges until this function is called again with flag being GL_FAL
00045 // for when drawing wireframe mode
00046 
00047 #ifndef ViewPort3D_C_DEFINED
00048 #define ViewPort3D_C_DEFINED
00049 
00050 #include "GUI/ViewPort3D.H"
00051 #include "Image/DrawOps.H"
00052 #include "GUI/DebugWin.H"
00053 #include <stdio.h>
00054 // ######################################################################
00055 ViewPort3D::ViewPort3D(const int width,const int height, 
00056     bool wireframe, bool useLights, bool useFeedback)  :
00057   itsScreenWidth(width),
00058   itsScreenHeight(height),
00059   itsCameraPosition(Point3D<float>(0,0,0)),
00060   itsCameraRotation(Point3D<float>(0,0,0)),
00061   itsShowRenderWindow(false),
00062   itsWireframe(wireframe),
00063   itsUseLights(useLights),
00064   itsUseFeedback(useFeedback),
00065   itsSphereQuality(5),
00066   itsCylinderQuality(5),
00067   itsSphereListNum(0),
00068   itsInitGlew(false)
00069 
00070 {
00071 
00072   //Initialize the window the the opengl
00073 
00074   itsDisplay = XOpenDisplay(0);
00075   if (!itsDisplay)
00076     LFATAL("Failed to open X display");
00077 
00078   // Get a matching FB config
00079   static int visual_attribs[] =
00080     {
00081       GLX_X_RENDERABLE    , True,
00082       GLX_DRAWABLE_TYPE   , GLX_WINDOW_BIT,
00083       GLX_RENDER_TYPE     , GLX_RGBA_BIT,
00084       GLX_X_VISUAL_TYPE   , GLX_TRUE_COLOR,
00085       GLX_RED_SIZE        , 8,
00086       GLX_GREEN_SIZE      , 8,
00087       GLX_BLUE_SIZE       , 8,
00088       GLX_ALPHA_SIZE      , 8,
00089       GLX_DEPTH_SIZE      , 24,
00090       GLX_STENCIL_SIZE    , 8,
00091       GLX_DOUBLEBUFFER    , True,
00092       //GLX_SAMPLE_BUFFERS  , 1,
00093       //GLX_SAMPLES         , 4,
00094       None
00095     };
00096 
00097   XVisualInfo *vi;
00098   LINFO( "Getting matching framebuffer configs" );
00099   int fbcount;
00100   GLXFBConfig *fbc = glXChooseFBConfig( itsDisplay, DefaultScreen( itsDisplay ),
00101                                         visual_attribs, &fbcount );
00102   if ( fbc )
00103   {
00104     LINFO( "Found %d matching FB configs.", fbcount );
00105 
00106     // Pick the FB config/visual with the most samples per pixel
00107     LINFO( "Getting XVisualInfos" );
00108     int best_fbc = -1, worst_fbc = -1, best_num_samp = -1, worst_num_samp = 999;
00109 
00110     for (int i = 0; i < fbcount; i++ )
00111     {
00112       XVisualInfo *tmpVi = glXGetVisualFromFBConfig( itsDisplay, fbc[i] );
00113       if ( tmpVi )
00114       {
00115         int samp_buf, samples;
00116         glXGetFBConfigAttrib( itsDisplay, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf );
00117         glXGetFBConfigAttrib( itsDisplay, fbc[i], GLX_SAMPLES       , &samples  );
00118 
00119         LINFO( "  Matching fbconfig %d, visual ID 0x%2x: SAMPLE_BUFFERS = %d,"
00120             " SAMPLES = %d",
00121             i, (uint)tmpVi -> visualid, samp_buf, samples );
00122 
00123         if ( best_fbc < 0 || (samp_buf && samples > best_num_samp) )
00124           best_fbc = i, best_num_samp = samples;
00125         if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp )
00126           worst_fbc = i, worst_num_samp = samples;
00127       }
00128       XFree( tmpVi );
00129     }
00130     // Get a visual
00131     //int fbc_id = best_fbc;
00132     int fbc_id = worst_fbc;
00133 
00134     vi = glXGetVisualFromFBConfig( itsDisplay, fbc[ fbc_id ]  );
00135     LINFO( "Chosen visual ID = 0x%x", (uint)vi->visualid );
00136   } else {
00137 
00138     int screen = DefaultScreen(itsDisplay);
00139     // get GL visual
00140     static int attribList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE,16,
00141       GLX_RED_SIZE,4, GLX_GREEN_SIZE,4,
00142       GLX_BLUE_SIZE,4, None};
00143     vi = glXChooseVisual (itsDisplay,screen,attribList);
00144   }
00145   if (!vi) LFATAL("no good X11 visual found for OpenGL");
00146 
00147   LINFO( "Creating colormap" );
00148   XSetWindowAttributes swa;
00149   swa.colormap = XCreateColormap( itsDisplay, RootWindow( itsDisplay, vi->screen ),
00150                                   vi->visual, AllocNone );
00151   swa.background_pixmap = None ;
00152   swa.border_pixel      = 0;
00153   swa.event_mask        = StructureNotifyMask;
00154 
00155   LINFO( "Creating window");
00156   itsWin = XCreateWindow( itsDisplay, RootWindow( itsDisplay, vi->screen ),
00157                               0, 0, itsScreenWidth, itsScreenHeight, 0,
00158                               vi->depth, InputOutput,
00159                               vi->visual,
00160                               CWBorderPixel|CWColormap|CWEventMask, &swa );
00161   if ( !itsWin )
00162     LFATAL( "Failed to create window." );
00163 
00164   if (itsShowRenderWindow)
00165   {
00166     XStoreName( itsDisplay, itsWin, "Render Window");
00167     XMapWindow( itsDisplay, itsWin ); //Enable this to show the window
00168   }
00169 
00170   // See if GL driver supports glXCreateContextAttribsARB()
00171   //   Create an old-style GLX context first, to get the correct function ptr.
00172   // glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
00173 
00174   GLXContext ctx_old = glXCreateContext( itsDisplay, vi, 0, True );
00175   //glXCreateContextAttribsARB = 
00176     (glXCreateContextAttribsARBProc)
00177            glXGetProcAddress( (const GLubyte *) "glXCreateContextAttribsARB" );
00178 
00179   itsCtx = ctx_old;
00180   XFree( fbc );
00181 
00182   // Verifying that context is a direct context
00183   //LINFO("Verifying that context is direct");
00184   //if ( ! glXIsDirect ( itsDisplay, itsCtx ) )
00185   //  LFATAL( "Indirect GLX rendering context obtained");
00186 
00187 
00188   //Set default camera projection matrix
00189   double cameraParam[3][4] = {
00190     {350.475735, 0, 158.250000, 0},
00191     {0.000000, -363.047091, 118.250000, 0.000000},
00192     {0.000000, 0.000000, 1.000000, 0.00000}};
00193   setProjectionMatrix(cameraParam);
00194 
00195   itsUseExParam = false;
00196 
00197 
00198   if (itsUseFeedback)
00199   {
00200     itsFeedbackBufferSize = 1024*1024;
00201     itsFeedbackBuffer = new float[itsFeedbackBufferSize];
00202   } else {
00203     itsFeedbackBufferSize = 0;
00204     itsFeedbackBuffer = NULL;
00205   }
00206 
00207 
00208 
00209 }
00210 
00211 ViewPort3D::~ViewPort3D()
00212 {
00213   delete[] itsFeedbackBuffer;
00214   glXMakeCurrent( itsDisplay, 0, 0 );
00215   glXDestroyContext( itsDisplay, itsCtx );
00216 }
00217 
00218 void ViewPort3D::initCtx()
00219 {
00220   glXMakeCurrent (itsDisplay,itsWin,itsCtx);
00221 }
00222 
00223 
00224 void ViewPort3D::initFrame()
00225 {
00226   glXMakeCurrent (itsDisplay,itsWin,itsCtx);
00227 
00228   //Draw and read from the back buffer
00229   glDrawBuffer(GL_BACK);
00230   glReadBuffer(GL_BACK);
00231 
00232   glEnable(GL_TEXTURE_2D);
00233   glShadeModel(GL_SMOOTH);
00234   glClearColor(0, 0, 0, 0.5);
00235   glClearDepth(1.0);
00236 
00237   //glDisable (GL_TEXTURE_GEN_S);
00238   //glDisable (GL_TEXTURE_GEN_T);
00239   //glShadeModel (GL_FLAT);
00240 
00241   glEnable (GL_CULL_FACE);
00242   glCullFace (GL_BACK);
00243   glFrontFace (GL_CCW);
00244 
00245   glEnable(GL_DEPTH_TEST); //enable depth testing
00246   glDepthFunc (GL_LESS);
00247 
00248   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Goot prespective calculations
00249 
00250   if (itsWireframe)
00251   {
00252     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //wireframe mode
00253     glLineWidth(1);
00254   }
00255   else
00256     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 
00257 
00258   if (itsUseLights)
00259     setLights();
00260   else
00261     glDisable(GL_LIGHTING);
00262 
00263   //Setup camera
00264   // Reset The Current Viewport
00265   glViewport(0,0,itsScreenWidth,itsScreenHeight);
00266 
00267   // Select The Projection Matrix
00268   glMatrixMode(GL_PROJECTION);
00269   glLoadMatrixd(itsProjMatrix);
00270 
00271   //Set the camera position and orientation
00272   glMatrixMode (GL_MODELVIEW);
00273   glLoadIdentity();
00274 
00275   if (itsUseExParam)
00276   {
00277     glLoadMatrixd( itsCameraExParam );
00278   } else {
00279     glLoadIdentity();
00280 
00281     glRotatef (180, 1,0,0); //Have the camera initialy look stright down
00282     glRotatef (itsCameraRotation.x, 1,0,0);
00283     glRotatef (itsCameraRotation.y, 0,1,0);
00284     glRotatef (-itsCameraRotation.z, 0,0,1);
00285     glTranslatef (-itsCameraPosition.x,-itsCameraPosition.y,-itsCameraPosition.z);
00286   }
00287 
00288   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);        // Clear Screen And Depth Buffer
00289 
00290   if (itsUseFeedback)
00291   {
00292     glFeedbackBuffer(itsFeedbackBufferSize, GL_2D, itsFeedbackBuffer);
00293     (void) glRenderMode(GL_FEEDBACK);
00294   }
00295 
00296 
00297 }
00298 
00299 void ViewPort3D::initProjection()
00300 {
00301   glXMakeCurrent (itsDisplay,itsWin,itsCtx);
00302 
00303   //Draw and read from the back buffer
00304   glDrawBuffer(GL_BACK);
00305   glReadBuffer(GL_BACK);
00306 
00307   glEnable(GL_TEXTURE_2D);
00308 
00309   //Setup camera
00310   // Reset The Current Viewport
00311   glViewport(0,0,itsScreenWidth,itsScreenHeight);
00312 
00313   //// Select The Projection Matrix
00314   glMatrixMode(GL_PROJECTION);
00315   glLoadIdentity();
00316   glOrtho(0.0,320,0.0,240, -1.0, 1.0);
00317   
00318 
00319   ////Set the camera position and orientation
00320   glMatrixMode (GL_MODELVIEW);
00321   glLoadIdentity();
00322 
00323   glClearColor(0, 0, 0, 0);
00324   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);        // Clear Screen And Depth Buffer
00325 
00326 }
00327 
00328 
00329 void ViewPort3D::setLights()
00330 {
00331 
00332   glEnable(GL_LIGHTING);
00333 
00334   //Configure overall ambient light
00335   GLfloat lModelAmbient[] = { 0.5, 0.5, 0.5, 1.0 };
00336   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lModelAmbient);
00337 
00338 
00339   //For more realistic lighting effects
00340   //glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
00341 
00342 
00343   //Illuminate the back faces as well
00344   //Should only be used if we have objects that are cut
00345   //so that the lightting will iluminate the back faces as well
00346   //glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
00347 
00348   //Configure light 0
00349   GLfloat LightAmbient[]= { 0.0f, 0.0f, 0.0f, 1.0f }; //Overall lighting
00350   GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f }; //RGB bright Directional light
00351   GLfloat LightPosition[]= { 100.0f, 100.0f, 2.0f, 0.0f }; //Position from above
00352 
00353   glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
00354   glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
00355   glLightfv(GL_LIGHT0, GL_POSITION,LightPosition);
00356   glEnable(GL_LIGHT0);
00357 
00358 }
00359 
00360 void ViewPort3D::setCamera ( const Point3D<float> pos,
00361                              const Point3D<float> rot )
00362 {
00363 
00364   itsCameraPosition = pos;
00365   itsCameraRotation = rot;
00366 }
00367 
00368 void ViewPort3D::setCamera ( const double trans[3][4])
00369 {
00370     for(int j = 0; j < 3; j++ ) {
00371       for(int i = 0; i < 4; i++ ) {
00372         itsCameraExParam[i*4+j] = trans[j][i];
00373       }
00374     }
00375     itsCameraExParam[0*4+3] = itsCameraExParam[1*4+3] = itsCameraExParam[2*4+3] = 0.0;
00376     itsCameraExParam[3*4+3] = 1.0;
00377 
00378     itsUseExParam = true;
00379 
00380 }
00381 
00382 Image<PixRGB<byte> > ViewPort3D::getFrame(){
00383 
00384   //Get the frame from the back buffer
00385 
00386   glFlush();
00387   Image<PixRGB<byte> > retImg(itsScreenWidth, itsScreenHeight, NO_INIT);
00388   glPixelStorei(GL_PACK_ALIGNMENT,1);
00389   glReadBuffer(GL_BACK_LEFT);
00390   glReadPixels (0, 0, itsScreenWidth, itsScreenHeight,
00391       GL_RGB, GL_UNSIGNED_BYTE,
00392       (unsigned char*)retImg.getArrayPtr());
00393 
00394   return retImg;
00395 }
00396 
00397 Image<PixRGB<float> > ViewPort3D::getFrameFloat(){
00398 
00399   //Get the frame from the back buffer
00400 
00401   glFlush();
00402   Image<PixRGB<float> > retImg(itsScreenWidth, itsScreenHeight, NO_INIT);
00403   glPixelStorei(GL_PACK_ALIGNMENT,1);
00404   glReadBuffer(GL_BACK_LEFT);
00405   glReadPixels (0, 0, itsScreenWidth, itsScreenHeight,
00406       GL_RGB, GL_FLOAT, retImg.getArrayPtr());
00407 
00408   return retImg;
00409 }
00410 
00411 Image<float> ViewPort3D::getDepthFrame(){
00412 
00413   //Get the frame from the back buffer
00414 
00415   glFlush();
00416   Image<float> retImg(itsScreenWidth, itsScreenHeight, NO_INIT);
00417   glPixelStorei(GL_PACK_ALIGNMENT,1);
00418   //glReadBuffer(GL_BACK_LEFT);
00419   glReadPixels (0, 0, itsScreenWidth, itsScreenHeight,
00420       GL_DEPTH_COMPONENT, GL_FLOAT,
00421       (unsigned char*)retImg.getArrayPtr());
00422   return retImg;
00423 }
00424 
00425 std::vector<ViewPort3D::Line> ViewPort3D::getFrameLines()
00426 {
00427   std::vector<Line> lines;
00428 
00429   if (itsUseFeedback)
00430   {
00431     int size = glRenderMode(GL_RENDER);
00432 
00433     if (size < 0)
00434       LFATAL("FeedbackBuffer too small, increase itsFeedbackSize");
00435 
00436     int count = size;
00437     while (count) {
00438       float token = itsFeedbackBuffer[size-count]; count--;
00439 
00440       if (token == GL_PASS_THROUGH_TOKEN) {
00441         LINFO("GL_PASS_THROUGH_TOKEN\n");
00442         LINFO("  %4.2f\n", itsFeedbackBuffer[size-count]);
00443         count--;
00444         if (count < 0) break;
00445       }
00446       else if (token == GL_POINT_TOKEN) {
00447         LINFO("GL_POINT_TOKEN\n");
00448         count -= 2;
00449         if (count < 0) break;
00450         //print3DcolorVertex (size, &count, buffer,x,y,z);
00451       }
00452       else if (token == GL_LINE_TOKEN) {
00453         Line l;
00454         l.p1.i = itsFeedbackBuffer[size-count+0];
00455         l.p1.j = itsScreenHeight-itsFeedbackBuffer[size-count+1];
00456 
00457         l.p2.i = itsFeedbackBuffer[size-count+2];
00458         l.p2.j = itsScreenHeight-itsFeedbackBuffer[size-count+3];
00459         count -= 4;
00460         if (count < 0) break;
00461 
00462         lines.push_back(l);
00463 
00464       }
00465       else if (token == GL_LINE_RESET_TOKEN) {
00466         Line l;
00467         l.p1.i = itsFeedbackBuffer[size-count+0];
00468         l.p1.j = itsScreenHeight-itsFeedbackBuffer[size-count+1];
00469 
00470         l.p2.i = itsFeedbackBuffer[size-count+2];
00471         l.p2.j = itsScreenHeight-itsFeedbackBuffer[size-count+3];
00472         count -= 4;
00473         if (count < 0) break;
00474 
00475         lines.push_back(l);
00476       }
00477     }
00478     
00479 
00480   } else {
00481     LFATAL("Need to enable feedback to use this function");
00482   }
00483 
00484 
00485   return lines;
00486 }
00487 
00488 
00489 Point3D<float> ViewPort3D::getPosition(Point3D<float> loc)
00490 {
00491   GLint viewport[4];
00492   GLdouble modelview[16];
00493   GLdouble projection[16];
00494   GLfloat winX, winY, winZ;
00495   GLdouble posX=0, posY=0, posZ=0;
00496 
00497   glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
00498   glGetDoublev( GL_PROJECTION_MATRIX, projection );
00499   glGetIntegerv( GL_VIEWPORT, viewport );
00500 
00501   winX = loc.x;
00502   winY = (float)viewport[3] - loc.y; //Flip the y
00503   winZ = loc.z;
00504   //glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);
00505   //LINFO("Win %f %f(%f) %f", winX, winY, (float)viewport[3], winZ);
00506 
00507 #ifdef INVT_HAVE_LIBGLUT
00508   gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
00509 #else
00510   LFATAL("Need lib Glut fro this function");
00511 #endif
00512 
00513   return Point3D<float>(posX, posY, posZ);
00514 
00515 }
00516 
00517 void ViewPort3D::setProjectionMatrix(float fovy, float aspect, float zmin, float zmax)
00518 {
00519 
00520  glXMakeCurrent (itsDisplay,itsWin,itsCtx);
00521  glViewport(0,0,itsScreenWidth,itsScreenHeight);
00522  glMatrixMode(GL_PROJECTION);
00523  glLoadIdentity();
00524 
00525  float xmin, xmax, ymin, ymax;
00526  ymax = zmin * tan(fovy * M_PI / 360.0);
00527  ymin = -ymax;
00528  xmin = ymin * aspect;
00529  xmax = ymax * aspect;
00530  glFrustum(xmin, xmax, ymin, ymax, zmin, zmax);
00531 
00532  //Save the projection matrix
00533  glGetDoublev(GL_PROJECTION_MATRIX, itsProjMatrix);
00534 
00535 }
00536 
00537 
00538 void ViewPort3D::setProjectionMatrix(const double cameraParam[3][4])
00539 {
00540   //Borrowed from ARTToolkit
00541 
00542   double   icpara[3][4];
00543   double   trans[3][4];
00544   double   p[3][3], q[4][4];
00545   int      i, j;
00546   double gnear = 0.1; //50;
00547   double gfar = 5000;
00548 
00549   if( paramDecompMat(cameraParam, icpara, trans) < 0 )
00550     LFATAL("Camera Parameter error!!\n");
00551 
00552   for( i = 0; i < 3; i++ ) {
00553     for( j = 0; j < 3; j++ ) {
00554       p[i][j] = icpara[i][j] / icpara[2][2];
00555     }
00556   }
00557   q[0][0] = (2.0 * p[0][0] / itsScreenWidth);
00558   q[0][1] = (2.0 * p[0][1] / itsScreenWidth);
00559   q[0][2] = ((2.0 * p[0][2] / itsScreenWidth)  - 1.0);
00560   q[0][3] = 0.0;
00561 
00562   q[1][0] = 0.0;
00563   q[1][1] = (2.0 * p[1][1] / itsScreenHeight);
00564   q[1][2] = ((2.0 * p[1][2] / itsScreenHeight) - 1.0);
00565   q[1][3] = 0.0;
00566 
00567   q[2][0] = 0.0;
00568   q[2][1] = 0.0;
00569   q[2][2] = (gfar + gnear)/(gfar - gnear);
00570   q[2][3] = -2.0 * gfar * gnear / (gfar - gnear);
00571 
00572   q[3][0] = 0.0;
00573   q[3][1] = 0.0;
00574   q[3][2] = 1.0;
00575   q[3][3] = 0.0;
00576 
00577   for( i = 0; i < 4; i++ ) {
00578     for( j = 0; j < 3; j++ ) {
00579       itsProjMatrix[i+j*4] = q[i][0] * trans[0][j]
00580                            + q[i][1] * trans[1][j]
00581                            + q[i][2] * trans[2][j];
00582     }
00583     itsProjMatrix[i+3*4] = q[i][0] * trans[0][3]
00584                          + q[i][1] * trans[1][3]
00585                          + q[i][2] * trans[2][3]
00586                          + q[i][3];
00587   }
00588 
00589 }
00590 
00591 #define NORM(a,b,c) sqrt(a*a + b*b + c*c)
00592 #define DOT(a1,a2,a3,b1,b2,b3) (a1*b1 + a2*b2 + a3*b3)
00593 
00594 int  ViewPort3D::paramDecompMat(const double source[3][4],
00595                                 double cpara[3][4],
00596                                 double trans[3][4] )
00597 {
00598   int       r, c;
00599   double    Cpara[3][4];
00600   double    rem1, rem2, rem3;
00601 
00602   if( source[2][3] >= 0 ) {
00603     for( r = 0; r < 3; r++ ){
00604       for( c = 0; c < 4; c++ ){
00605         Cpara[r][c] = source[r][c];
00606       }
00607     }
00608   }
00609   else {
00610     for( r = 0; r < 3; r++ ){
00611       for( c = 0; c < 4; c++ ){
00612         Cpara[r][c] = -(source[r][c]);
00613       }
00614     }
00615   }
00616 
00617   for( r = 0; r < 3; r++ ){
00618     for( c = 0; c < 4; c++ ){
00619       cpara[r][c] = 0.0;
00620     }
00621   }
00622   cpara[2][2] = NORM( Cpara[2][0], Cpara[2][1], Cpara[2][2] );
00623   trans[2][0] = Cpara[2][0] / cpara[2][2];
00624   trans[2][1] = Cpara[2][1] / cpara[2][2];
00625   trans[2][2] = Cpara[2][2] / cpara[2][2];
00626   trans[2][3] = Cpara[2][3] / cpara[2][2];
00627 
00628   cpara[1][2] = DOT( trans[2][0], trans[2][1], trans[2][2],
00629       Cpara[1][0], Cpara[1][1], Cpara[1][2] );
00630   rem1 = Cpara[1][0] - cpara[1][2] * trans[2][0];
00631   rem2 = Cpara[1][1] - cpara[1][2] * trans[2][1];
00632   rem3 = Cpara[1][2] - cpara[1][2] * trans[2][2];
00633   cpara[1][1] = NORM( rem1, rem2, rem3 );
00634   trans[1][0] = rem1 / cpara[1][1];
00635   trans[1][1] = rem2 / cpara[1][1];
00636   trans[1][2] = rem3 / cpara[1][1];
00637 
00638   cpara[0][2] = DOT( trans[2][0], trans[2][1], trans[2][2],
00639       Cpara[0][0], Cpara[0][1], Cpara[0][2] );
00640   cpara[0][1] = DOT( trans[1][0], trans[1][1], trans[1][2],
00641       Cpara[0][0], Cpara[0][1], Cpara[0][2] );
00642   rem1 = Cpara[0][0] - cpara[0][1]*trans[1][0] - cpara[0][2]*trans[2][0];
00643   rem2 = Cpara[0][1] - cpara[0][1]*trans[1][1] - cpara[0][2]*trans[2][1];
00644   rem3 = Cpara[0][2] - cpara[0][1]*trans[1][2] - cpara[0][2]*trans[2][2];
00645   cpara[0][0] = NORM( rem1, rem2, rem3 );
00646   trans[0][0] = rem1 / cpara[0][0];
00647   trans[0][1] = rem2 / cpara[0][0];
00648   trans[0][2] = rem3 / cpara[0][0];
00649 
00650   trans[1][3] = (Cpara[1][3] - cpara[1][2]*trans[2][3]) / cpara[1][1];
00651   trans[0][3] = (Cpara[0][3] - cpara[0][1]*trans[1][3]
00652       - cpara[0][2]*trans[2][3]) / cpara[0][0];
00653 
00654   for( r = 0; r < 3; r++ ){
00655     for( c = 0; c < 3; c++ ){
00656       cpara[r][c] /= cpara[2][2];
00657     }
00658   }
00659 
00660   return 0;
00661 }
00662 
00663 
00664 ////////////////////////////////////////////////////////////////////////////
00665 
00666 void ViewPort3D::setColor(const PixRGB<byte> color)
00667 {
00668 
00669   float r = color[0]/256.0;
00670   float g = color[1]/256.0;
00671   float b = color[2]/256.0;
00672 
00673   if (itsUseLights)
00674   {
00675     GLfloat light_ambient[4],light_diffuse[4],light_specular[4];
00676     light_ambient[0] = r*0.3f;
00677     light_ambient[1] = g*0.3f;
00678     light_ambient[2] = b*0.3f;
00679     light_ambient[3] = 1; //alpha
00680     light_diffuse[0] = r*0.7f;
00681     light_diffuse[1] = g*0.7f;
00682     light_diffuse[2] = b*0.7f;
00683     light_diffuse[3] = 1; //alpha
00684     light_specular[0] = r*0.2f;
00685     light_specular[1] = g*0.2f;
00686     light_specular[2] = b*0.2f;
00687     light_specular[3] = 1; //alpha
00688 
00689     glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, light_ambient);
00690     glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, light_diffuse);
00691     glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, light_specular);
00692     glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 50.0f);
00693   } else {
00694     //Simple color
00695     glColor3f(r,g,b);
00696   }
00697 
00698 }
00699 
00700 void ViewPort3D::drawGrid(Dims size, Dims step, float height)
00701 {
00702 
00703   glPushMatrix();
00704 
00705   glTranslatef(0, 0, 0);
00706   glRotatef(0, 1,0,0);
00707   glRotatef(0, 0,1,0);
00708   glRotatef(0, 0,0,1);
00709 
00710   glBegin(GL_LINES);
00711   //Horizontal lines
00712   for(float i=-size.w()/2; i<=size.w()/2; i+=step.w())
00713   {
00714     glVertex3f( -size.h()/2,i,height);
00715     glVertex3f( size.h()/2,i,height);
00716   }
00717 
00718   //Vertical lines
00719   for(float i=-size.h()/2; i<=size.h()/2; i+=step.h())
00720   {
00721     glVertex3f(i, -size.w()/2,height);
00722     glVertex3f(i, size.w()/2,height);
00723   }
00724 
00725   glEnd();                 
00726 
00727   glPopMatrix();
00728 
00729 }
00730 
00731 void ViewPort3D::drawLine(const Point3D<float>& p1, const Point3D<float>& p2)
00732 {
00733   glPushMatrix();
00734 
00735   glTranslatef(0, 0, 0);
00736   glRotatef(0, 1,0,0);
00737   glRotatef(0, 0,1,0);
00738   glRotatef(0, 0,0,1);
00739 
00740   glBegin(GL_LINES);
00741     glVertex3f(p1.x, p1.y, p1.z);
00742     glVertex3f(p2.x, p2.y, p2.z);
00743   glEnd();                 
00744 
00745   glPopMatrix();
00746 
00747 }
00748 
00749 
00750 void ViewPort3D::drawRectangle(const Point3D<float> pos,
00751                        const Point3D<float> rot, //Rotation
00752                        const float width, const float height,
00753                        const PixRGB<byte> color)
00754 {
00755 
00756   glPushMatrix();
00757   setColor(color);
00758 
00759   glShadeModel (GL_FLAT);
00760 
00761   glTranslatef(pos.x, pos.y, pos.z);
00762   glRotatef(rot.x, 1,0,0);
00763   glRotatef(rot.y, 0,1,0);
00764   glRotatef(rot.z, 0,0,1);
00765 
00766   double lx = width*0.5f;
00767   double ly = height*0.5f;
00768 
00769   glBegin(GL_QUADS);
00770   glNormal3f(0,0,1);
00771   glTexCoord2i(0, 0);  glVertex3f( lx, ly, 0);                        // Top Right Of The Quad (Front)
00772   glTexCoord2i(0, 1);  glVertex3f(-lx, ly, 0);                        // Top Left Of The Quad (Front)
00773   glTexCoord2i(1, 1);  glVertex3f(-lx,-ly, 0);                        // Bottom Left Of The Quad (Front)
00774   glTexCoord2i(1, 0);  glVertex3f( lx,-ly, 0);                        // Bottom Right Of The Quad (Front)
00775   glEnd();                                                          // Done Drawing The Quad
00776 
00777   glPopMatrix();
00778 
00779 }
00780 
00781 
00782 void ViewPort3D::drawDisk(const Point3D<float> pos,
00783                        const Point3D<float> rot, //Rotation
00784                        const float radius,
00785                        const PixRGB<byte> color)
00786 {
00787   glPushMatrix();
00788   setColor(color);
00789   glShadeModel (GL_SMOOTH);
00790 
00791   glTranslatef(pos.x, pos.y, pos.z);
00792   glRotatef(rot.x, 1,0,0);
00793   glRotatef(rot.y, 0,1,0);
00794   glRotatef(rot.z, 0,0,1);
00795 
00796   //// number of sides to the cylinder (divisible by 4):
00797   const int n = itsCylinderQuality*4;
00798 
00799   double a = double(M_PI*2.0)/double(n);
00800   double sa = (double) sin(a);
00801   double ca = (double) cos(a);
00802 
00803   // draw circle
00804   glShadeModel (GL_FLAT);
00805   double ny=1;
00806   double nz=0;                  // normal vector = (0,ny,nz)
00807   glBegin (GL_TRIANGLE_FAN);
00808   glNormal3d (0,0,1);
00809   glVertex3d (0,0,0);
00810   for (int i=0; i<=n; i++) {
00811     glVertex3d (ny*radius,nz*radius,0);
00812 
00813     // rotate ny,nz
00814     double tmp = ca*ny - sa*nz;
00815     nz = sa*ny + ca*nz;
00816     ny = tmp;
00817   }
00818   glEnd();
00819 
00820   glPopMatrix();
00821 }
00822 
00823 void ViewPort3D::drawCircle(const Point3D<float> pos,
00824                        const Point3D<float> rot, //Rotation
00825                        const float radius,
00826                        const PixRGB<byte> color)
00827 {
00828   glPushMatrix();
00829   setColor(color);
00830   glShadeModel (GL_SMOOTH);
00831 
00832   glTranslatef(pos.x, pos.y, pos.z);
00833   glRotatef(rot.x, 1,0,0);
00834   glRotatef(rot.y, 0,1,0);
00835   glRotatef(rot.z, 0,0,1);
00836 
00837   //// number of sides to the cylinder (divisible by 4):
00838   const int n = itsCylinderQuality*4;
00839 
00840   double a = double(M_PI*2.0)/double(n);
00841   double sa = (double) sin(a);
00842   double ca = (double) cos(a);
00843 
00844   // draw circle
00845   double ny=1;
00846   double nz=0;                  // normal vector = (0,ny,nz)
00847   glBegin(GL_LINE_LOOP);
00848   for(int i=0; i<=n; i++)
00849   {
00850     glVertex3d( ny*radius, nz*radius,0);
00851     // rotate ny,nz
00852     double tmp = ca*ny - sa*nz;
00853     nz = sa*ny + ca*nz;
00854     ny = tmp;
00855   }
00856 
00857   glEnd();                 
00858 
00859   glPopMatrix();
00860 }
00861 
00862 void ViewPort3D::drawEllipse(const Point3D<float> pos,
00863                        const Point3D<float> rot, //Rotation
00864                        const float radiusX, const float radiusY,
00865                        const PixRGB<byte> color)
00866 {
00867   glPushMatrix();
00868   setColor(color);
00869   glShadeModel (GL_SMOOTH);
00870 
00871   glTranslatef(pos.x, pos.y, pos.z);
00872   glRotatef(rot.x, 1,0,0);
00873   glRotatef(rot.y, 0,1,0);
00874   glRotatef(rot.z, 0,0,1);
00875 
00876   //// number of sides to the cylinder (divisible by 4):
00877   const int n = itsCylinderQuality*4;
00878 
00879   double a = double(M_PI*2.0)/double(n);
00880   double sa = (double) sin(a);
00881   double ca = (double) cos(a);
00882 
00883   // draw circle
00884   double ny=1;
00885   double nz=0;                  // normal vector = (0,ny,nz)
00886   glBegin(GL_LINE_LOOP);
00887   for(int i=0; i<=n; i++)
00888   {
00889     glVertex3d( ny*radiusX, nz*radiusY,0);
00890     // rotate ny,nz
00891     double tmp = ca*ny - sa*nz;
00892     nz = sa*ny + ca*nz;
00893     ny = tmp;
00894   }
00895 
00896   glEnd();                 
00897 
00898   glPopMatrix();
00899 }
00900 
00901 
00902 void ViewPort3D::drawBox(const Point3D<float> pos,
00903                        const Point3D<float> rot, //Rotation
00904                        const Point3D<float> size,
00905                        const PixRGB<byte> color)
00906 {
00907 
00908   glPushMatrix();
00909   setColor(color);
00910 
00911   glShadeModel (GL_FLAT);
00912 
00913   glTranslatef(pos.x, pos.y, pos.z);
00914   glRotatef(rot.x, 1,0,0);
00915   glRotatef(rot.y, 0,1,0);
00916   glRotatef(rot.z, 0,0,1);
00917 
00918   double lx = size.x*0.5f;
00919   double ly = size.y*0.5f;
00920   double lz = size.z*0.5f;
00921 
00922   glBegin(GL_QUADS);
00923   glNormal3f(0,1,0);
00924   glTexCoord2i(0, 0);  glVertex3f( lx, ly,-lz);                        // Top Right Of The Quad (Top)
00925   glTexCoord2i(0, 1);  glVertex3f(-lx, ly,-lz);                        // Top Left Of The Quad (Top)
00926   glTexCoord2i(1, 1);  glVertex3f(-lx, ly, lz);                        // Bottom Left Of The Quad (Top)
00927   glTexCoord2i(1, 0);  glVertex3f( lx, ly, lz);                        // Bottom Right Of The Quad (Top)
00928 
00929   glNormal3f(0,-1,0);
00930   glTexCoord2i(0, 0);  glVertex3f( lx,-ly, lz);                        // Top Right Of The Quad (Bottom)
00931   glTexCoord2i(0, 1);  glVertex3f(-lx,-ly, lz);                        // Top Left Of The Quad (Bottom)
00932   glTexCoord2i(1, 1);  glVertex3f(-lx,-ly,-lz);                        // Bottom Left Of The Quad (Bottom)
00933   glTexCoord2i(1, 0);  glVertex3f( lx,-ly,-lz);                        // Bottom Right Of The Quad (Bottom)
00934 
00935   glNormal3f(0,0,1);
00936   glTexCoord2i(0, 0);  glVertex3f( lx, ly, lz);                        // Top Right Of The Quad (Front)
00937   glTexCoord2i(0, 1);  glVertex3f(-lx, ly, lz);                        // Top Left Of The Quad (Front)
00938   glTexCoord2i(1, 1);  glVertex3f(-lx,-ly, lz);                        // Bottom Left Of The Quad (Front)
00939   glTexCoord2i(1, 0);  glVertex3f( lx,-ly, lz);                        // Bottom Right Of The Quad (Front)
00940 
00941   glNormal3f(0,0,-1);
00942   glTexCoord2i(0, 0);  glVertex3f( lx,-ly,-lz);                        // Bottom Left Of The Quad (Back)
00943   glTexCoord2i(0, 1);  glVertex3f(-lx,-ly,-lz);                        // Bottom Right Of The Quad (Back)
00944   glTexCoord2i(1, 1);  glVertex3f(-lx, ly,-lz);                        // Top Right Of The Quad (Back)
00945   glTexCoord2i(1, 0);  glVertex3f( lx, ly,-lz);                        // Top Left Of The Quad (Back)
00946 
00947   glNormal3f(-1,0,0);
00948   glTexCoord2i(0, 0);  glVertex3f(-lx, ly, lz);                        // Top Right Of The Quad (Left)
00949   glTexCoord2i(0, 1);  glVertex3f(-lx, ly,-lz);                        // Top Left Of The Quad (Left)
00950   glTexCoord2i(1, 1);  glVertex3f(-lx,-ly,-lz);                        // Bottom Left Of The Quad (Left)
00951   glTexCoord2i(1, 0);  glVertex3f(-lx,-ly, lz);                        // Bottom Right Of The Quad (Left)
00952 
00953   glNormal3f(1,0,0);
00954   glTexCoord2i(0, 0);  glVertex3f( lx, ly,-lz);                        // Top Right Of The Quad (Right)
00955   glTexCoord2i(0, 1);  glVertex3f( lx, ly, lz);                        // Top Left Of The Quad (Right)
00956   glTexCoord2i(1, 1);  glVertex3f( lx,-ly, lz);                        // Bottom Left Of The Quad (Right)
00957   glTexCoord2i(1, 0);  glVertex3f( lx,-ly,-lz);                        // Bottom Right Of The Quad (Right)
00958   glEnd();                                                          // Done Drawing The Quad
00959 
00960   glPopMatrix();
00961 
00962 }
00963 
00964 void ViewPort3D::drawSphere(const Point3D<float> pos,
00965                        const Point3D<float> rot, //Rotation
00966                        const Point3D<float> size,
00967                        const PixRGB<byte> color)
00968 {
00969 
00970   glPushMatrix();
00971 
00972   setColor(color);
00973 
00974   //Enable normalize because we scale the sphere and dont want color and lights to
00975   //get scaled as well (they need to have a mag of 1)
00976   //However, normalize slows things down, so we only use it for sphere
00977   glEnable (GL_NORMALIZE);
00978 
00979   glShadeModel (GL_SMOOTH);
00980 
00981   glTranslatef(pos.x, pos.y, pos.z);
00982   glRotatef(rot.x, 1,0,0);
00983   glRotatef(rot.y, 0,1,0);
00984   glRotatef(rot.z, 0,0,1);
00985   glScaled (size.x,size.y,size.z);
00986 
00987 
00988   if (itsSphereListNum == 0)
00989     itsSphereListNum = generateSphere(itsSphereQuality);
00990 
00991   if (itsSphereListNum != 0)
00992     glCallList (itsSphereListNum);
00993 
00994   glDisable (GL_NORMALIZE);
00995 
00996   glPopMatrix();
00997 }
00998 
00999 uint ViewPort3D::generateSphere(int quality)
01000 {
01001 
01002   // icosahedron data for an icosahedron of radius 1.0
01003 # define ICX 0.525731112119133606f
01004 # define ICZ 0.850650808352039932f
01005   static GLdouble idata[12][3] = {
01006     {-ICX, 0, ICZ},
01007     {ICX, 0, ICZ},
01008     {-ICX, 0, -ICZ},
01009     {ICX, 0, -ICZ},
01010     {0, ICZ, ICX},
01011     {0, ICZ, -ICX},
01012     {0, -ICZ, ICX},
01013     {0, -ICZ, -ICX},
01014     {ICZ, ICX, 0},
01015     {-ICZ, ICX, 0},
01016     {ICZ, -ICX, 0},
01017     {-ICZ, -ICX, 0}
01018   };
01019 
01020   static int index[20][3] = {
01021     {0, 4, 1},          {0, 9, 4},
01022     {9, 5, 4},          {4, 5, 8},
01023     {4, 8, 1},          {8, 10, 1},
01024     {8, 3, 10},   {5, 3, 8},
01025     {5, 2, 3},          {2, 7, 3},
01026     {7, 10, 3},   {7, 6, 10},
01027     {7, 11, 6},   {11, 0, 6},
01028     {0, 1, 6},          {6, 1, 10},
01029     {9, 0, 11},   {9, 11, 2},
01030     {9, 2, 5},          {7, 2, 11},
01031   };
01032 
01033   uint listnum = glGenLists (1);
01034   glNewList (listnum,GL_COMPILE);
01035   glBegin (GL_TRIANGLES);
01036   for (int i=0; i<20; i++) {
01037     drawPatch (&idata[index[i][2]][0],&idata[index[i][1]][0],
01038         &idata[index[i][0]][0],quality);
01039   }
01040   glEnd();
01041   glEndList();
01042 
01043   return listnum;
01044 
01045 }
01046 
01047 void ViewPort3D::drawPatch (double p1[3], double p2[3], double p3[3], int level)
01048 {
01049   int i;
01050   if (level > 0) {
01051     double q1[3],q2[3],q3[3];                 // sub-vertices
01052     for (i=0; i<3; i++) {
01053       q1[i] = 0.5f*(p1[i]+p2[i]);
01054       q2[i] = 0.5f*(p2[i]+p3[i]);
01055       q3[i] = 0.5f*(p3[i]+p1[i]);
01056     }
01057     double length1 = (double)(1.0/sqrt(q1[0]*q1[0]+q1[1]*q1[1]+q1[2]*q1[2]));
01058     double length2 = (double)(1.0/sqrt(q2[0]*q2[0]+q2[1]*q2[1]+q2[2]*q2[2]));
01059     double length3 = (double)(1.0/sqrt(q3[0]*q3[0]+q3[1]*q3[1]+q3[2]*q3[2]));
01060     for (i=0; i<3; i++) {
01061       q1[i] *= length1;
01062       q2[i] *= length2;
01063       q3[i] *= length3;
01064     }
01065     drawPatch (p1,q1,q3,level-1);
01066     drawPatch (q1,p2,q2,level-1);
01067     drawPatch (q1,q2,q3,level-1);
01068     drawPatch (q3,q2,p3,level-1);
01069   }
01070   else {
01071     glNormal3f (p1[0],p1[1],p1[2]);
01072     glVertex3f (p1[0],p1[1],p1[2]);
01073     glNormal3f (p2[0],p2[1],p2[2]);
01074     glVertex3f (p2[0],p2[1],p2[2]);
01075     glNormal3f (p3[0],p3[1],p3[2]);
01076     glVertex3f (p3[0],p3[1],p3[2]);
01077   }
01078 }
01079 
01080 void ViewPort3D::drawCappedCylinder(const Point3D<float> pos,
01081                        const Point3D<float> rot, //Rotation
01082                        const float radius,
01083                        const float length,
01084                        const PixRGB<byte> color)
01085 {
01086 
01087   glPushMatrix();
01088 
01089   setColor(color);
01090 
01091   glShadeModel (GL_SMOOTH);
01092 
01093   glTranslatef(pos.x, pos.y, pos.z);
01094   glRotatef(rot.x, 1,0,0);
01095   glRotatef(rot.y, 0,1,0);
01096   glRotatef(rot.z, 0,0,1);
01097 
01098   // number of sides to the cylinder (divisible by 4):
01099   const int n = itsCylinderQuality*4;
01100 
01101   float halfLength = length * 0.5;
01102 
01103   double a = double(M_PI*2.0)/double(n);
01104   double sa = (double) sin(a);
01105   double ca = (double) cos(a);
01106 
01107   // draw cylinder body
01108   double ny=1, nz=0;                  // normal vector = (0,ny,nz)
01109   glBegin (GL_TRIANGLE_STRIP);
01110   for (int i=0; i<=n; i++) {
01111     glNormal3d (ny,nz,0);
01112     glVertex3d (ny*radius,nz*radius,halfLength);
01113     glNormal3d (ny,nz,0);
01114     glVertex3d (ny*radius,nz*radius,-halfLength);
01115     // rotate ny,nz
01116     double tmp = ca*ny - sa*nz;
01117     nz = sa*ny + ca*nz;
01118     ny = tmp;
01119   }
01120   glEnd();
01121 
01122   // draw first cylinder cap
01123   double start_nx = 0;
01124   double start_ny = 1;
01125   for (int j=0; j<(n/4); j++) {
01126     // get start_n2 = rotated start_n
01127     double start_nx2 =  ca*start_nx + sa*start_ny;
01128     double start_ny2 = -sa*start_nx + ca*start_ny;
01129     // get n=start_n and n2=start_n2
01130     double nx = start_nx, ny = start_ny, nz = 0;
01131     double nx2 = start_nx2, ny2 = start_ny2, nz2 = 0;
01132     glBegin (GL_TRIANGLE_STRIP);
01133     for (int i=0; i<=n; i++) {
01134       glNormal3d (ny2,nz2,nx2);
01135       glVertex3d (ny2*radius,nz2*radius,halfLength+nx2*radius);
01136       glNormal3d (ny,nz,nx);
01137       glVertex3d (ny*radius,nz*radius,halfLength+nx*radius);
01138       // rotate n,n2
01139       double tmp = ca*ny - sa*nz;
01140       nz = sa*ny + ca*nz;
01141       ny = tmp;
01142       tmp = ca*ny2- sa*nz2;
01143       nz2 = sa*ny2 + ca*nz2;
01144       ny2 = tmp;
01145     }
01146     glEnd();
01147     start_nx = start_nx2;
01148     start_ny = start_ny2;
01149   }
01150 
01151   // draw second cylinder cap
01152   start_nx = 0;
01153   start_ny = 1;
01154   for (int j=0; j<(n/4); j++) {
01155     // get start_n2 = rotated start_n
01156     double start_nx2 = ca*start_nx - sa*start_ny;
01157     double start_ny2 = sa*start_nx + ca*start_ny;
01158     // get n=start_n and n2=start_n2
01159     double nx = start_nx, ny = start_ny, nz = 0;
01160     double nx2 = start_nx2, ny2 = start_ny2, nz2 = 0;
01161     glBegin (GL_TRIANGLE_STRIP);
01162     for (int i=0; i<=n; i++) {
01163       glNormal3d (ny,nz,nx);
01164       glVertex3d (ny*radius,nz*radius,-halfLength+nx*radius);
01165       glNormal3d (ny2,nz2,nx2);
01166       glVertex3d (ny2*radius,nz2*radius,-halfLength+nx2*radius);
01167       // rotate n,n2
01168       double tmp = ca*ny - sa*nz;
01169       nz = sa*ny + ca*nz;
01170       ny = tmp;
01171       tmp = ca*ny2- sa*nz2;
01172       nz2 = sa*ny2 + ca*nz2;
01173       ny2 = tmp;
01174     }
01175     glEnd();
01176     start_nx = start_nx2;
01177     start_ny = start_ny2;
01178   }
01179 
01180   glPopMatrix();
01181 }
01182 
01183 void ViewPort3D::drawCylinder(const Point3D<float> pos,
01184                        const Point3D<float> rot, //Rotation
01185                        const float radius,
01186                        const float length,
01187                        const PixRGB<byte> color)
01188 {
01189 
01190   glPushMatrix();
01191 
01192   setColor(color);
01193 
01194   glShadeModel (GL_SMOOTH);
01195 
01196   glTranslatef(pos.x, pos.y, pos.z);
01197   glRotatef(rot.x, 1,0,0);
01198   glRotatef(rot.y, 0,1,0);
01199   glRotatef(rot.z, 0,0,1);
01200 
01201   // number of sides to the cylinder (divisible by 4):
01202   const int n = itsCylinderQuality*4;
01203 
01204   float halfLength = length * 0.5;
01205 
01206   double a = double(M_PI*2.0)/double(n);
01207   double sa = (double) sin(a);
01208   double ca = (double) cos(a);
01209 
01210   // draw cylinder body
01211   double ny=1, nz=0;                  // normal vector = (0,ny,nz)
01212   glBegin (GL_TRIANGLE_STRIP);
01213   for (int i=0; i<=n; i++) {
01214     glNormal3d (ny,nz,0);
01215     glVertex3d (ny*radius,nz*radius,halfLength);
01216     glNormal3d (ny,nz,0);
01217     glVertex3d (ny*radius,nz*radius,-halfLength);
01218     // rotate ny,nz
01219     double tmp = ca*ny - sa*nz;
01220     nz = sa*ny + ca*nz;
01221     ny = tmp;
01222   }
01223   glEnd();
01224 
01225   // draw top cap
01226   glShadeModel (GL_FLAT);
01227   ny=1, nz=0;                  // normal vector = (0,ny,nz)
01228   glBegin (GL_TRIANGLE_FAN);
01229   glNormal3d (0,0,1);
01230   glVertex3d (0,0,halfLength);
01231   for (int i=0; i<=n; i++) {
01232     //if (i==1 || i==n/2+1)
01233     //  setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
01234     glNormal3d (0,0,1);
01235     glVertex3d (ny*radius,nz*radius,halfLength);
01236     //if (i==1 || i==n/2+1)
01237     //  setColor (color[0],color[1],color[2],color[3]);
01238 
01239     // rotate ny,nz
01240     double tmp = ca*ny - sa*nz;
01241     nz = sa*ny + ca*nz;
01242     ny = tmp;
01243   }
01244   glEnd();
01245 
01246   // draw bottom cap
01247   ny=1; nz=0;                  // normal vector = (0,ny,nz)
01248   glBegin (GL_TRIANGLE_FAN);
01249   glNormal3d (0,0,-1);
01250   glVertex3d (0,0,-halfLength);
01251   for (int i=0; i<=n; i++) {
01252     //if (i==1 || i==n/2+1)
01253     //  setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
01254     glNormal3d (0,0,-1);
01255     glVertex3d (ny*radius,nz*radius,-halfLength);
01256     //if (i==1 || i==n/2+1)
01257     //  setColor (color[0],color[1],color[2],color[3]);
01258 
01259     // rotate ny,nz
01260     double tmp = ca*ny + sa*nz;
01261     nz = -sa*ny + ca*nz;
01262     ny = tmp;
01263   }
01264   glEnd();
01265 
01266 
01267   glPopMatrix();
01268 }
01269 
01270 void ViewPort3D::drawCone(const Point3D<float> pos,
01271                        const Point3D<float> rot, //Rotation
01272                        const float radius,
01273                        const float length,
01274                        const PixRGB<byte> color)
01275 {
01276 
01277   glPushMatrix();
01278 
01279   setColor(color);
01280 
01281   glShadeModel (GL_SMOOTH);
01282 
01283   glTranslatef(pos.x, pos.y, pos.z);
01284   glRotatef(rot.x, 1,0,0);
01285   glRotatef(rot.y, 0,1,0);
01286   glRotatef(rot.z, 0,0,1);
01287 
01288   // number of sides to the cylinder (divisible by 4):
01289   const int n = itsCylinderQuality*4;
01290 
01291   float halfLength = length * 0.5;
01292 
01293   double a = double(M_PI*2.0)/double(n);
01294   double sa = (double) sin(a);
01295   double ca = (double) cos(a);
01296 
01297   glShadeModel (GL_FLAT);
01298 
01299   glFrontFace(GL_CW);
01300   // draw bottom cap
01301   double ny=1; double nz=0;                  // normal vector = (0,ny,nz)
01302   glBegin (GL_TRIANGLE_FAN);
01303   glNormal3d (0,0,1);
01304   glVertex3d (0,0,-halfLength);
01305   for (int i=0; i<=n; i++) {
01306     glNormal3d (0,0,1);
01307     glVertex3d (ny*radius,nz*radius,-halfLength);
01308     // rotate ny,nz
01309     double tmp = ca*ny + sa*nz;
01310     nz = -sa*ny + ca*nz;
01311     ny = tmp;
01312   }
01313   glEnd();
01314 
01315   glFrontFace(GL_CCW);
01316   // draw body
01317   ny=1; nz=0;                  // normal vector = (0,ny,nz)
01318   glBegin (GL_TRIANGLE_FAN);
01319   glNormal3d (0,0,-1);
01320   glVertex3d (0,0,halfLength);
01321   for (int i=0; i<=n; i++) {
01322     glNormal3d (ny,nz,0);
01323     glVertex3d (ny*radius,nz*radius,-halfLength);
01324     // rotate ny,nz
01325     double tmp = ca*ny + sa*nz;
01326     nz = -sa*ny + ca*nz;
01327     ny = tmp;
01328   }
01329   glEnd();
01330 
01331   glPopMatrix();
01332 }
01333 
01334 
01335 void ViewPort3D::drawGround(const Point2D<float> size, const PixRGB<byte> color)
01336 {
01337 
01338   glPushMatrix();
01339   setColor(color);
01340   glShadeModel (GL_FLAT);
01341   glTranslatef(0, 0, 0);
01342 
01343   glBegin(GL_QUADS);
01344 
01345   glNormal3f(0,0,1);
01346   glVertex3f( size.i, size.j, 0);                        // Top Right Of The Quad (Front)
01347   glVertex3f(-size.i, size.j, 0);                        // Top Left Of The Quad (Front)
01348   glVertex3f(-size.i,-size.j, 0);                        // Bottom Left Of The Quad (Front)
01349   glVertex3f( size.i,-size.j, 0);                        // Bottom Right Of The Quad (Front)
01350 
01351   glEnd();                                                          // Done Drawing The Quad
01352 
01353   glPopMatrix();
01354 
01355 }
01356 
01357 
01358 
01359 
01360 void ViewPort3D::drawExtrudedContour(const std::vector<Point2D<float> >& contour,
01361     const Point3D<float> pos,
01362     const Point3D<float> rot,
01363     const float thickness,
01364     const PixRGB<byte> color)
01365 {
01366   std::vector<Point2D<float> > triangles = triangulate(contour);
01367 
01368   glPushMatrix();
01369   setColor(color);
01370 
01371   glShadeModel (GL_SMOOTH);
01372 
01373   glTranslatef(pos.x, pos.y, pos.z);
01374   glRotatef(rot.x, 1,0,0);
01375   glRotatef(rot.y, 0,1,0);
01376   glRotatef(rot.z, 0,0,1);
01377 
01378   //Draw the first side
01379   glFrontFace(GL_CW);
01380   glBegin(GL_TRIANGLES);
01381   glNormal3f(0,0,-1);
01382   for(uint i=0; i<triangles.size(); i++)
01383   {
01384     glVertex3f(triangles[i].i, triangles[i].j,-thickness/2);                        // Top Right Of The Quad (Top)
01385   }
01386   glEnd();
01387 
01388   glBegin(GL_QUAD_STRIP);
01389   uint numPoints = contour.size();
01390   for(uint i=0; i<numPoints; i++)
01391   {
01392     glVertex3f(contour[i].i, contour[i].j,-thickness/2);                        // Top Right Of The Quad (Top)
01393     glVertex3f(contour[i].i, contour[i].j,thickness/2);                        // Top Right Of The Quad (Top)
01394     glVertex3f(contour[(i+1)%numPoints].i, contour[(i+1)%numPoints].j,-thickness/2);                        // Top Right Of The Quad (Top)
01395     glVertex3f(contour[(i+1)%numPoints].i, contour[(i+1)%numPoints].j,thickness/2);                        // Top Right Of The Quad (Top)
01396 
01397     double dx = contour[(i+1)%numPoints].j - contour[i].j;
01398     double dy = contour[i].i - contour[(i+1)%numPoints].i;
01399     double len = sqrt(dx * dx + dy * dy);
01400     glNormal3f(dx / len, dy / len, 0.0);
01401   }
01402   glEnd();
01403 
01404   glFrontFace(GL_CCW);
01405   ////Draw the next side
01406   glBegin(GL_TRIANGLES);
01407   glNormal3f(0,0,1);
01408   for(uint i=0; i<triangles.size(); i++)
01409   {
01410     //glNormal3f(0,0,1);
01411     glVertex3f(triangles[i].i, triangles[i].j, thickness/2);                        // Top Right Of The Quad (Top)
01412   }
01413   glEnd();
01414 
01415   glPopMatrix();
01416 }
01417 
01418 
01419 bool ViewPort3D::snip(const std::vector<Point2D<float> > &contour,
01420                             int u,int v,int w,int n,int *V)
01421 {
01422 
01423   Point2D<float> A = contour[V[u]];
01424   Point2D<float> B = contour[V[v]];
01425   Point2D<float> C = contour[V[w]];
01426 
01427   const float EPSILON=0.0000000001f;
01428 
01429   if ( EPSILON > (((B.i-A.i)*(C.j-A.j)) - ((B.j-A.j)*(C.i-A.i))) ) return false;
01430 
01431   for (int p=0;p<n;p++)
01432   {
01433     if( (p == u) || (p == v) || (p == w) ) continue;
01434     Point2D<float> P = contour[V[p]];
01435     if (pnTriangle(A,B,C,P)) return false;
01436   }
01437 
01438   return true;
01439 }
01440 
01441 //Borowed from John W. Ratcliff [jratcliff@verant.com] and adapted to work with Point2D class
01442 //http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml
01443 std::vector<Point2D<float> > ViewPort3D::triangulate(const std::vector<Point2D<float> >& contour)
01444 {
01445   std::vector<Point2D<float> > result;
01446 
01447   int n = contour.size();
01448   if ( n < 3 ) return result;
01449 
01450   int *V = new int[n];
01451 
01452   /* we want a counter-clockwise polygon in V */
01453 
01454   if ( 0.0f < area(contour) )
01455     for (int v=0; v<n; v++) V[v] = v;
01456   else
01457     for(int v=0; v<n; v++) V[v] = (n-1)-v;
01458 
01459   int nv = n;
01460 
01461   /*  remove nv-2 Vertices, creating 1 triangle every time */
01462   int count = 2*nv;   /* error detection */
01463 
01464   for(int m=0, v=nv-1; nv>2; )
01465   {
01466     /* if we loop, it is probably a non-simple polygon */
01467     if (0 >= (count--))
01468     {
01469       //** Triangulate: ERROR - probable bad polygon!
01470       return result;
01471     }
01472 
01473     /* three consecutive vertices in current polygon, <u,v,w> */
01474     int u = v  ; if (nv <= u) u = 0;     /* previous */
01475     v = u+1; if (nv <= v) v = 0;     /* new v    */
01476     int w = v+1; if (nv <= w) w = 0;     /* next     */
01477 
01478     if ( snip(contour,u,v,w,nv,V) )
01479     {
01480       int a,b,c,s,t;
01481 
01482       /* true names of the vertices */
01483       a = V[u]; b = V[v]; c = V[w];
01484 
01485       /* output Triangle */
01486       result.push_back( contour[a] );
01487       result.push_back( contour[b] );
01488       result.push_back( contour[c] );
01489 
01490       m++;
01491 
01492       /* remove v from remaining polygon */
01493       for(s=v,t=v+1;t<nv;s++,t++) V[s] = V[t]; nv--;
01494 
01495       /* resest error detection counter */
01496       count = 2*nv;
01497     }
01498   }
01499 
01500   delete V;
01501 
01502   return result;
01503 
01504 }
01505 
01506 uint ViewPort3D::addTexture(const Image<PixRGB<byte> >& textureImg)
01507 {
01508   uint texId;
01509   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01510 
01511   glGenTextures(1, &texId);
01512   glBindTexture(GL_TEXTURE_2D, texId);
01513 
01514   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
01515   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
01516   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
01517   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
01518 
01519   //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01520   //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01521   //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
01522   //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
01523 
01524 
01525   unsigned char* arrayPtr =  const_cast<unsigned char*>
01526     (reinterpret_cast<const unsigned char*> (textureImg.getArrayPtr()));
01527   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
01528       textureImg.getWidth(), textureImg.getHeight(),
01529       0, GL_RGB, GL_UNSIGNED_BYTE, 
01530       arrayPtr);
01531 
01532   return texId;
01533 
01534 }
01535 
01536 uint ViewPort3D::addTexture(const Image<float>& textureImg)
01537 {
01538   uint texId;
01539   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
01540 
01541   glGenTextures(1, &texId);
01542   glBindTexture(GL_TEXTURE_2D, texId);
01543 
01544   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
01545   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
01546   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
01547   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
01548 
01549   //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
01550   //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
01551   //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
01552   //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
01553 
01554 
01555   unsigned char* arrayPtr =  const_cast<unsigned char*>
01556     (reinterpret_cast<const unsigned char*> (textureImg.getArrayPtr()));
01557   glTexImage2D(GL_TEXTURE_2D, 0, GL_FLOAT,
01558       textureImg.getWidth(), textureImg.getHeight(),
01559       0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 
01560       arrayPtr);
01561 
01562   return texId;
01563 
01564 }
01565 
01566 void ViewPort3D::loadTexture(const Image<PixRGB<byte> >& textureImg, uint texId)
01567 {
01568   glBindTexture(GL_TEXTURE_2D, texId);
01569 
01570   unsigned char* arrayPtr =  const_cast<unsigned char*>
01571     (reinterpret_cast<const unsigned char*> (textureImg.getArrayPtr()));
01572   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
01573       textureImg.getWidth(), textureImg.getHeight(),
01574       0, GL_RGB, GL_UNSIGNED_BYTE, 
01575       arrayPtr);
01576 
01577 }
01578 
01579 
01580 void ViewPort3D::bindTexture(const uint texId)
01581 {
01582   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
01583   glBindTexture(GL_TEXTURE_2D, texId);
01584 
01585 }
01586 
01587 #ifdef HAVE_GL_GLEW_H
01588 
01589 void ViewPort3D::printInfoLog(GLhandleARB obj)
01590 {
01591   int infologLength = 0;
01592   int charsWritten  = 0;
01593   char *infoLog;
01594 
01595   glGetObjectParameterivARB(obj, GL_OBJECT_INFO_LOG_LENGTH_ARB,
01596       &infologLength);
01597 
01598   if (infologLength > 0)
01599   {
01600     infoLog = (char *)malloc(infologLength);
01601     glGetInfoLogARB(obj, infologLength, &charsWritten, infoLog);
01602     LINFO("%s",infoLog);
01603     free(infoLog);
01604   }
01605   
01606 
01607 }
01608 //! Shader support
01609 GLhandleARB ViewPort3D::createShader(const char *prog, int type)
01610 {
01611 
01612   if (!itsInitGlew)
01613   {
01614     glewInit();
01615     if (GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
01616       LINFO("Ready for GLSL\n");
01617     else
01618       LFATAL("No GLSL support\n");
01619     itsInitGlew=true;
01620   }
01621   
01622 
01623   //Read the text file into memory
01624 
01625   FILE *fp = fopen(prog, "rt");
01626   if (fp == NULL)
01627     LFATAL("Can not find shader program %s", prog);
01628 
01629   //Find the size of the prog
01630   fseek(fp, 0, SEEK_END);
01631   int count = ftell(fp);
01632   rewind(fp);
01633 
01634   char* progContent = NULL;
01635   if (count > 0)
01636   {
01637     progContent = (char *)malloc(sizeof(char) * (count+1));
01638     count = fread(progContent, sizeof(char), count, fp);
01639     progContent[count] = '\0';
01640   }
01641   fclose(fp);
01642 
01643   if (progContent == NULL)
01644     LFATAL("Can not load program");
01645 
01646   GLhandleARB h;
01647 
01648   h = glCreateShaderObjectARB(type);
01649 
01650   LINFO("Add program\n");
01651   glShaderSourceARB(h, 1, (const char**)&progContent,NULL);
01652   LINFO("Done");
01653 
01654   glCompileShaderARB(h);
01655 
01656   LINFO("Compiling Shader");
01657   printInfoLog(h);
01658 
01659   GLhandleARB p = glCreateProgramObjectARB();
01660   glAttachObjectARB(p,h);
01661   glLinkProgramARB(p);
01662   printInfoLog(p);
01663   glUseProgramObjectARB(p);
01664 
01665   return p;
01666 }
01667 
01668 void ViewPort3D::progToTexture(const GLhandleARB prog, const int texId)
01669 
01670 {
01671         glUseProgramObjectARB(prog);
01672         initProjection();
01673   glBegin(GL_QUADS);
01674   glTexCoord2f(0.0, 0.0); glVertex3f(0, 0, 0);
01675   glTexCoord2f(1.0, 0.0); glVertex3f(320, 0, 0);
01676   glTexCoord2f(1.0, 1.0); glVertex3f(320, 240 , 0);
01677   glTexCoord2f(0.0, 1.0); glVertex3f(0, 240, 0);
01678   glEnd();
01679   
01680         glFlush();
01681   if (texId != -1) //Render to a diffrent texture
01682                 glBindTexture(GL_TEXTURE_2D, texId);
01683         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 5, 5, 0, 0, 320-10,240-10);
01684 
01685 
01686 }
01687 
01688 #endif
01689 
01690 
01691 
01692 
01693 
01694 // ######################################################################
01695 /* So things look consistent in everyone's emacs... */
01696 /* Local Variables: */
01697 /* indent-tabs-mode: nil */
01698 /* End: */
01699 
01700 #endif
01701 
Generated on Sun May 8 08:40:41 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3