ViewPort.C

00001 /*!@file GUI/Viewport.C test opengl viewport */
00002 
00003 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2003   //
00004 // by the University of Southern California (USC) and the iLab at USC.  //
00005 // See http://iLab.usc.edu for information about this project.          //
00006 // //////////////////////////////////////////////////////////////////// //
00007 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00008 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00009 // in Visual Environments, and Applications'' by Christof Koch and      //
00010 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00011 // pending; application number 09/912,225 filed July 23, 2001; see      //
00012 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00013 // //////////////////////////////////////////////////////////////////// //
00014 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00015 //                                                                      //
00016 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00017 // redistribute it and/or modify it under the terms of the GNU General  //
00018 // Public License as published by the Free Software Foundation; either  //
00019 // version 2 of the License, or (at your option) any later version.     //
00020 //                                                                      //
00021 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00022 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00023 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00024 // PURPOSE.  See the GNU General Public License for more details.       //
00025 //                                                                      //
00026 // You should have received a copy of the GNU General Public License    //
00027 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00028 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00029 // Boston, MA 02111-1307 USA.                                           //
00030 // //////////////////////////////////////////////////////////////////// //
00031 // Primary maintainer for this file: Lior Elazary <elazary@usc.edu>
00032 // Originally obtained from ode
00033 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/GUI/ViewPort.C $
00034 // $Id: ViewPort.C 14563 2011-03-02 01:09:49Z dberg $
00035 
00036 
00037 #include "GUI/ViewPort.H"
00038 #include <math.h>
00039 #include <pthread.h>
00040 #include <sys/stat.h>
00041 
00042 //TODO: we need to only draw a new camera position of the current rendering. NOt rander the whole thing. Can Use glViewPort
00043 
00044 ViewPort::ViewPort(const char *winname,
00045     const char* ground, const char* sky, bool useFog,
00046     bool drawWorld,
00047     int w, int h,
00048     const double cameraParam[3][4] ) :
00049   itsWidth(w),
00050   itsHeight(h),
00051   run(0),
00052   display(0),
00053   visual(0),
00054   colormap(0),
00055   win(0),
00056   glx_context(0),
00057   last_key_pressed(0),
00058   wm_protocols_atom(0),
00059   wm_delete_window_atom(0),
00060   screen(0),
00061   sky_texture(0),
00062   ground_texture(0),
00063   wood_texture(0),
00064   tree_texture(0),
00065   other_texture(0),
00066   listnum(0),
00067   itsDrawWorld(drawWorld),
00068   itsUseFog(useFog),
00069   itsWireframe(false),
00070   itsZoomFactor(0.8)
00071 {
00072   createMainWindow (winname);
00073 
00074   glXMakeCurrent (display,win,glx_context);
00075   startGraphics("./etc/textures/", ground, sky);
00076 
00077   for(int i=0; i<4; i++)
00078     color[i] = 0;
00079   tnum = 0;                        // current texture number
00080 
00081   ground_scale = 1.0f/20.0f;        // ground texture scale (1/size)
00082   ground_ofsx = 0.5;                // offset of ground texture
00083   ground_ofsy = 0.5;
00084   sky_scale = 1.0f/4.0f;        // sky texture scale (1/size)
00085   sky_height = 1.0f;                // sky height above viewpoint
00086 
00087   sphere_quality = 1;
00088   capped_cylinder_quality = 3;
00089 
00090   if (itsDrawWorld)
00091   {
00092     use_textures=1;                // 1 if textures to be drawn
00093     use_shadows=1;                // 1 if shadows to be drawn
00094   } else {
00095     use_textures=0;                // 1 if textures to be drawn
00096     use_shadows=0;                // 1 if shadows to be drawn
00097   }
00098 
00099 
00100   initCamera();                //set the camera to initail position
00101 
00102   if (cameraParam != NULL)
00103     buildProjectionMatrix(cameraParam, itsProjMatrix);
00104 
00105   run = 1;
00106   //int rc = pthread_create(&win_thread, NULL, ViewPort::mainWindowThread, this);
00107   //if (rc){
00108   //        LFATAL("Error creating main window thread\n");
00109   //}
00110   //mainWindowThread(this);
00111 }
00112 
00113 ViewPort::~ViewPort(){
00114   stopGraphics();
00115 
00116   destroyMainWindow();
00117 }
00118 
00119 void ViewPort::setTextures(bool val)
00120 {
00121   if (val)
00122     use_textures=1;
00123   else
00124     use_textures=0;
00125 }
00126 
00127 void ViewPort::setShadows(bool val)
00128 {
00129   if (val)
00130     use_shadows=1;
00131   else
00132     use_shadows=0;
00133 }
00134 
00135 
00136 void ViewPort::createMainWindow (const char *winname){
00137 
00138   display = XOpenDisplay (NULL);
00139   if (!display) LFATAL("can not open X11 display");
00140 
00141   screen = DefaultScreen(display);
00142 
00143 
00144   // get GL visual
00145   static int attribList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE,16,
00146     GLX_RED_SIZE,4, GLX_GREEN_SIZE,4,
00147     GLX_BLUE_SIZE,4, None};
00148   visual = glXChooseVisual (display,screen,attribList);
00149   if (!visual) LFATAL("no good X11 visual found for OpenGL");
00150 
00151   // create colormap
00152   colormap = XCreateColormap (display,RootWindow(display,screen),
00153       visual->visual,AllocNone);
00154 
00155   // initialize variables
00156   win = 0;
00157   //glx_context = 0;
00158   last_key_pressed = 0;
00159 
00160   if (itsWidth < 1 || itsHeight < 1) LDEBUG ("bad window width or height");
00161 
00162   // create the window
00163   XSetWindowAttributes attributes;
00164   attributes.background_pixel = BlackPixel(display,screen);
00165   attributes.colormap = colormap;
00166   attributes.event_mask = ButtonPressMask | ButtonReleaseMask |
00167     KeyPressMask | KeyReleaseMask | ButtonMotionMask | PointerMotionHintMask |
00168     StructureNotifyMask;
00169   win = XCreateWindow (display,RootWindow(display,screen),50,50,itsWidth,itsHeight,
00170       0,visual->depth, InputOutput,visual->visual,
00171       CWBackPixel | CWColormap | CWEventMask,&attributes);
00172 
00173   // associate a GLX context with the window
00174   glx_context = glXCreateContext (display,visual,0,GL_TRUE);
00175   if (!glx_context) LFATAL ("can't make an OpenGL context");
00176 
00177   // set the window title
00178   XTextProperty window_name;
00179   window_name.value = (unsigned char *)winname; //(unsigned char *) "Simulation";
00180   window_name.encoding = XA_STRING;
00181   window_name.format = 8;
00182   window_name.nitems = strlen((char *) window_name.value);
00183   XSetWMName (display,win,&window_name);
00184 
00185   // participate in the window manager 'delete yourself' protocol
00186   wm_protocols_atom = XInternAtom (display,"WM_PROTOCOLS",False);
00187   wm_delete_window_atom = XInternAtom (display,"WM_DELETE_WINDOW",False);
00188   if (XSetWMProtocols (display,win,&wm_delete_window_atom,1)==0)
00189     LFATAL ("XSetWMProtocols() call failed");
00190 
00191   // pop up the window
00192   XMapWindow (display,win);
00193   XSync (display,win);
00194 
00195 }
00196 
00197 void ViewPort::destroyMainWindow()
00198 {
00199   glXDestroyContext (display,glx_context);
00200   XDestroyWindow (display,win);
00201   XSync (display,0);
00202   display = 0;
00203   win = 0;
00204   glx_context = NULL;
00205 }
00206 
00207 
00208 void ViewPort::startGraphics (const char *prefix, const char *ground, const char *sky){
00209   // All examples build into the same dir
00210   char *s =  new char[strlen(prefix) + 20];
00211 
00212   strcpy (s,prefix);
00213   strcat (s,sky);
00214   sky_texture = new Texture (s);
00215 
00216   strcpy (s,prefix);
00217   strcat (s,ground);
00218   ground_texture = new Texture (s);
00219 
00220   strcpy (s,prefix);
00221   strcat (s,"wood.ppm");
00222   wood_texture = new Texture (s);
00223 
00224   strcpy (s,prefix);
00225   strcat (s,"tree.ppm");
00226   tree_texture = new Texture (s);
00227 }
00228 
00229 void ViewPort::stopGraphics()
00230 {
00231   if (sky_texture) delete sky_texture;
00232   if (ground_texture) delete ground_texture;
00233   if (wood_texture) delete wood_texture;
00234   if (tree_texture) delete tree_texture;
00235   if (other_texture) delete other_texture;
00236   sky_texture = 0;
00237   ground_texture = 0;
00238   tree_texture = 0;
00239   other_texture = 0;
00240 }
00241 
00242 void ViewPort::handleEvent (XEvent &event)
00243 {
00244   static int mx=0,my=0;         // mouse position
00245   static int mode = 0;                // mouse button bits
00246 
00247   //LDEBUG("Handeling event %i\n", event.type);
00248 
00249   switch (event.type) {
00250 
00251     case ButtonPress: {
00252                         if (event.xbutton.button == Button1) mode |= 1;
00253                         if (event.xbutton.button == Button2) mode |= 2;
00254                         if (event.xbutton.button == Button3) mode |= 4;
00255                         mx = event.xbutton.x;
00256                         my = event.xbutton.y;
00257                       }
00258                       return;
00259 
00260     case ButtonRelease: {
00261                           if (event.xbutton.button == Button1) mode &= (~1);
00262                           if (event.xbutton.button == Button2) mode &= (~2);
00263                           if (event.xbutton.button == Button3) mode &= (~4);
00264                           mx = event.xbutton.x;
00265                           my = event.xbutton.x;
00266                         }
00267                         return;
00268 
00269     case MotionNotify: {
00270                          if (event.xmotion.is_hint) {
00271                            Window root,child;
00272                            unsigned int mask;
00273                            XQueryPointer (display,win,&root,&child,&event.xbutton.x_root,
00274                                &event.xbutton.y_root,&event.xbutton.x,&event.xbutton.y,
00275                                &mask);
00276                          }
00277                          dsMotion (mode, event.xmotion.x - mx, event.xmotion.y - my);
00278                          mx = event.xmotion.x;
00279                          my = event.xmotion.y;
00280                        }
00281                        return;
00282 
00283     case ClientMessage:
00284                        if (event.xclient.message_type == wm_protocols_atom &&
00285                            event.xclient.format == 32 &&
00286                            Atom(event.xclient.data.l[0]) == wm_delete_window_atom) {
00287                          run = 0;
00288                          return;
00289                        }
00290                        return;
00291 
00292     case ConfigureNotify:
00293                        itsWidth = event.xconfigure.width;
00294                        itsHeight = event.xconfigure.height;
00295                        return;
00296   }
00297 }
00298 
00299 void ViewPort::initCamera()
00300 {
00301   view_xyz[0] = 0;
00302   view_xyz[1] = 5;
00303   view_xyz[2] = 5;
00304   view_hpr[0] = -100;
00305   view_hpr[1] = -30;
00306   view_hpr[2] = 0;
00307 }
00308 
00309 
00310 //!init the frame and process window events before drawing stuff
00311 XEvent ViewPort::initFrame(const double* cameraParam){
00312 
00313   ////process enevent for the window
00314   XEvent event;
00315   while (run && XPending (display)) {
00316     XNextEvent (display,&event);
00317     handleEvent (event);
00318   }
00319 
00320   dsDrawFrame (cameraParam);
00321 
00322   return event;
00323 }
00324 
00325 
00326 //! update the frame and return if we are running or not
00327 int ViewPort::updateFrame(){
00328 
00329   glFlush();
00330   glXSwapBuffers (display,win);
00331   XSync (display,0);
00332 
00333   return run;
00334 
00335 }
00336 
00337 void ViewPort::getFrame(unsigned char *img){
00338   glXMakeCurrent (display,win,glx_context);
00339   glPixelStorei(GL_PACK_ALIGNMENT,1);
00340   glReadBuffer(GL_BACK_LEFT);
00341   glReadPixels (0, 0, itsWidth, itsHeight, GL_RGB, GL_UNSIGNED_BYTE, img);
00342 }
00343 
00344 Image<PixRGB<byte> > ViewPort::getFrame(){
00345 
00346   Image<PixRGB<byte> > retImg(itsWidth, itsHeight, NO_INIT);
00347   glXMakeCurrent (display,win,glx_context);
00348   glPixelStorei(GL_PACK_ALIGNMENT,1);
00349   glReadBuffer(GL_BACK_LEFT);
00350   glReadPixels (0, 0, itsWidth, itsHeight, GL_RGB, GL_UNSIGNED_BYTE, (unsigned char*)retImg.getArrayPtr());
00351 
00352   return retImg;
00353 }
00354 
00355 void ViewPort::mainWindowThread(void *data){
00356   ViewPort *vp = (ViewPort *)data;
00357   vp->run = 1;
00358   while(vp->run){
00359     XEvent event;
00360     while (vp->run && XPending (vp->display)) {
00361       XNextEvent (vp->display,&event);
00362       vp->handleEvent (event);
00363     }
00364 
00365     //vp->dsDrawFrame ();
00366 
00367     glFlush();
00368     glXSwapBuffers (vp->display,vp->win);
00369     XSync (vp->display,0);
00370 
00371     // capture frames if necessary
00372     if (vp->writeframes) {
00373       //captureFrame (frame);
00374       //frame++;
00375     }
00376   }
00377 
00378 }
00379 
00380 inline double ViewPort::dDOT (const double *a, const double *b)
00381 { return ((a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2]); }
00382 
00383 
00384 void ViewPort::normalizeVector3 (float v[3])
00385 {
00386   double len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
00387   if (len <= 0.0f) {
00388     v[0] = 1;
00389     v[1] = 0;
00390     v[2] = 0;
00391   }
00392   else {
00393     len = 1.0f / (double)sqrt(len);
00394     v[0] *= len;
00395     v[1] *= len;
00396     v[2] *= len;
00397   }
00398 }
00399 
00400 //***************************************************************************
00401 // OpenGL utility stuff
00402 
00403 void ViewPort::buildProjectionMatrix(const double cameraParam[3][4], double projMatrix[16])
00404 {
00405   //Borrowed from ARTToolkit
00406 
00407   double   icpara[3][4];
00408   double   trans[3][4];
00409   double   p[3][3], q[4][4];
00410   int      i, j;
00411   double gnear = 50;
00412   double gfar = 5000;
00413 
00414   if( paramDecompMat(cameraParam, icpara, trans) < 0 )
00415     LFATAL("Camera Parameter error!!\n");
00416 
00417   for( i = 0; i < 3; i++ ) {
00418     for( j = 0; j < 3; j++ ) {
00419       p[i][j] = icpara[i][j] / icpara[2][2];
00420     }
00421   }
00422   q[0][0] = (2.0 * p[0][0] / itsWidth);
00423   q[0][1] = (2.0 * p[0][1] / itsWidth);
00424   q[0][2] = ((2.0 * p[0][2] / itsWidth)  - 1.0);
00425   q[0][3] = 0.0;
00426 
00427   q[1][0] = 0.0;
00428   q[1][1] = (2.0 * p[1][1] / itsHeight);
00429   q[1][2] = ((2.0 * p[1][2] / itsHeight) - 1.0);
00430   q[1][3] = 0.0;
00431 
00432   q[2][0] = 0.0;
00433   q[2][1] = 0.0;
00434   q[2][2] = (gfar + gnear)/(gfar - gnear);
00435   q[2][3] = -2.0 * gfar * gnear / (gfar - gnear);
00436 
00437   q[3][0] = 0.0;
00438   q[3][1] = 0.0;
00439   q[3][2] = 1.0;
00440   q[3][3] = 0.0;
00441 
00442   for( i = 0; i < 4; i++ ) {
00443     for( j = 0; j < 3; j++ ) {
00444       projMatrix[i+j*4] = q[i][0] * trans[0][j]
00445         + q[i][1] * trans[1][j]
00446         + q[i][2] * trans[2][j];
00447     }
00448     projMatrix[i+3*4] = q[i][0] * trans[0][3]
00449       + q[i][1] * trans[1][3]
00450       + q[i][2] * trans[2][3]
00451       + q[i][3];
00452   }
00453 
00454 }
00455 
00456 #define NORM(a,b,c) sqrt(a*a + b*b + c*c)
00457 #define DOT(a1,a2,a3,b1,b2,b3) (a1*b1 + a2*b2 + a3*b3)
00458 
00459 int  ViewPort::paramDecompMat(const double source[3][4], double cpara[3][4], double trans[3][4] )
00460 {
00461   int       r, c;
00462   double    Cpara[3][4];
00463   double    rem1, rem2, rem3;
00464 
00465   if( source[2][3] >= 0 ) {
00466     for( r = 0; r < 3; r++ ){
00467       for( c = 0; c < 4; c++ ){
00468         Cpara[r][c] = source[r][c];
00469       }
00470     }
00471   }
00472   else {
00473     for( r = 0; r < 3; r++ ){
00474       for( c = 0; c < 4; c++ ){
00475         Cpara[r][c] = -(source[r][c]);
00476       }
00477     }
00478   }
00479 
00480   for( r = 0; r < 3; r++ ){
00481     for( c = 0; c < 4; c++ ){
00482       cpara[r][c] = 0.0;
00483     }
00484   }
00485   cpara[2][2] = NORM( Cpara[2][0], Cpara[2][1], Cpara[2][2] );
00486   trans[2][0] = Cpara[2][0] / cpara[2][2];
00487   trans[2][1] = Cpara[2][1] / cpara[2][2];
00488   trans[2][2] = Cpara[2][2] / cpara[2][2];
00489   trans[2][3] = Cpara[2][3] / cpara[2][2];
00490 
00491   cpara[1][2] = DOT( trans[2][0], trans[2][1], trans[2][2],
00492       Cpara[1][0], Cpara[1][1], Cpara[1][2] );
00493   rem1 = Cpara[1][0] - cpara[1][2] * trans[2][0];
00494   rem2 = Cpara[1][1] - cpara[1][2] * trans[2][1];
00495   rem3 = Cpara[1][2] - cpara[1][2] * trans[2][2];
00496   cpara[1][1] = NORM( rem1, rem2, rem3 );
00497   trans[1][0] = rem1 / cpara[1][1];
00498   trans[1][1] = rem2 / cpara[1][1];
00499   trans[1][2] = rem3 / cpara[1][1];
00500 
00501   cpara[0][2] = DOT( trans[2][0], trans[2][1], trans[2][2],
00502       Cpara[0][0], Cpara[0][1], Cpara[0][2] );
00503   cpara[0][1] = DOT( trans[1][0], trans[1][1], trans[1][2],
00504       Cpara[0][0], Cpara[0][1], Cpara[0][2] );
00505   rem1 = Cpara[0][0] - cpara[0][1]*trans[1][0] - cpara[0][2]*trans[2][0];
00506   rem2 = Cpara[0][1] - cpara[0][1]*trans[1][1] - cpara[0][2]*trans[2][1];
00507   rem3 = Cpara[0][2] - cpara[0][1]*trans[1][2] - cpara[0][2]*trans[2][2];
00508   cpara[0][0] = NORM( rem1, rem2, rem3 );
00509   trans[0][0] = rem1 / cpara[0][0];
00510   trans[0][1] = rem2 / cpara[0][0];
00511   trans[0][2] = rem3 / cpara[0][0];
00512 
00513   trans[1][3] = (Cpara[1][3] - cpara[1][2]*trans[2][3]) / cpara[1][1];
00514   trans[0][3] = (Cpara[0][3] - cpara[0][1]*trans[1][3]
00515       - cpara[0][2]*trans[2][3]) / cpara[0][0];
00516 
00517   for( r = 0; r < 3; r++ ){
00518     for( c = 0; c < 3; c++ ){
00519       cpara[r][c] /= cpara[2][2];
00520     }
00521   }
00522 
00523   return 0;
00524 }
00525 
00526 
00527 
00528 void ViewPort::setCamera (double x, double y, double z, double h, double p, double r)
00529 {
00530   glMatrixMode (GL_MODELVIEW);
00531   glLoadIdentity();
00532   glRotatef (90, 0,0,1);
00533   glRotatef (90, 0,1,0);
00534   glRotatef (r, 1,0,0);
00535   glRotatef (p, 0,1,0);
00536   glRotatef (-h, 0,0,1);
00537   glTranslatef (-x,-y,-z);
00538 }
00539 
00540 
00541 // sets the material color, not the light color
00542 
00543 void ViewPort::setColor (double r, double g, double b, double alpha)
00544 {
00545   GLfloat light_ambient[4],light_diffuse[4],light_specular[4];
00546   light_ambient[0] = r*0.3f;
00547   light_ambient[1] = g*0.3f;
00548   light_ambient[2] = b*0.3f;
00549   light_ambient[3] = alpha;
00550   light_diffuse[0] = r*0.7f;
00551   light_diffuse[1] = g*0.7f;
00552   light_diffuse[2] = b*0.7f;
00553   light_diffuse[3] = alpha;
00554   light_specular[0] = r*0.2f;
00555   light_specular[1] = g*0.2f;
00556   light_specular[2] = b*0.2f;
00557   light_specular[3] = alpha;
00558   glMaterialfv (GL_FRONT_AND_BACK, GL_AMBIENT, light_ambient);
00559   glMaterialfv (GL_FRONT_AND_BACK, GL_DIFFUSE, light_diffuse);
00560   glMaterialfv (GL_FRONT_AND_BACK, GL_SPECULAR, light_specular);
00561   glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 5.0f);
00562 }
00563 
00564 
00565 void ViewPort::setTransform (const double pos[3], const double R[12])
00566 {
00567   GLfloat matrix[16];
00568   matrix[0]=R[0];
00569   matrix[1]=R[4];
00570   matrix[2]=R[8];
00571   matrix[3]=0;
00572   matrix[4]=R[1];
00573   matrix[5]=R[5];
00574   matrix[6]=R[9];
00575   matrix[7]=0;
00576   matrix[8]=R[2];
00577   matrix[9]=R[6];
00578   matrix[10]=R[10];
00579   matrix[11]=0;
00580   matrix[12]=pos[0];
00581   matrix[13]=pos[1];
00582   matrix[14]=pos[2];
00583   matrix[15]=1;
00584   glPushMatrix();
00585   glMultMatrixf (matrix);
00586 }
00587 
00588 void ViewPort::unProjectPoint(const int x, const int y, double objLoc[3])
00589 {
00590 
00591   //From http://nehe.gamedev.net/data/articles/article.asp?article=13
00592   GLint viewport[4];
00593   GLdouble modelview[16];
00594   GLdouble projection[16];
00595   GLfloat winX=0, winY=0, winZ=0;
00596   GLdouble posX=0, posY=0, posZ=0;
00597 
00598   glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
00599   glGetDoublev( GL_PROJECTION_MATRIX, projection );
00600   glGetIntegerv( GL_VIEWPORT, viewport );
00601 
00602   winX = (float)x;
00603   winY = (float)viewport[3] - (float)y;
00604   glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
00605 
00606 
00607 #ifdef INVT_HAVE_LIBGLUT
00608   gluUnProject( winX, winY, winZ, modelview, projection, viewport, &posX, &posY, &posZ);
00609 #endif
00610 
00611   objLoc[0] = posX;
00612   objLoc[1] = posY;
00613   objLoc[2] = posZ;
00614 
00615 }
00616 
00617 // set shadow projection transform
00618 
00619 void ViewPort::setShadowTransform()
00620 {
00621   GLfloat matrix[16];
00622   for (int i=0; i<16; i++) matrix[i] = 0;
00623   matrix[0]=1;
00624   matrix[5]=1;
00625   matrix[8]=-LIGHTX;
00626   matrix[9]=-LIGHTY;
00627   matrix[15]=1;
00628   glPushMatrix();
00629   glMultMatrixf (matrix);
00630 }
00631 
00632 
00633 void ViewPort::drawBox (const double sides[3])
00634 {
00635   double lx = sides[0]*0.5f;
00636   double ly = sides[1]*0.5f;
00637   double lz = sides[2]*0.5f;
00638 
00639   glBegin(GL_QUADS);
00640   glNormal3f(0,1,0);
00641   glVertex3f( lx, ly,-lz);                        // Top Right Of The Quad (Top)
00642   glVertex3f(-lx, ly,-lz);                        // Top Left Of The Quad (Top)
00643   glVertex3f(-lx, ly, lz);                        // Bottom Left Of The Quad (Top)
00644   glVertex3f( lx, ly, lz);                        // Bottom Right Of The Quad (Top)
00645 
00646   glNormal3f(0,-1,0);
00647   glVertex3f( lx,-ly, lz);                        // Top Right Of The Quad (Bottom)
00648   glVertex3f(-lx,-ly, lz);                        // Top Left Of The Quad (Bottom)
00649   glVertex3f(-lx,-ly,-lz);                        // Bottom Left Of The Quad (Bottom)
00650   glVertex3f( lx,-ly,-lz);                        // Bottom Right Of The Quad (Bottom)
00651 
00652   glNormal3f(0,0,1);
00653   glVertex3f( lx, ly, lz);                        // Top Right Of The Quad (Front)
00654   glVertex3f(-lx, ly, lz);                        // Top Left Of The Quad (Front)
00655   glVertex3f(-lx,-ly, lz);                        // Bottom Left Of The Quad (Front)
00656   glVertex3f( lx,-ly, lz);                        // Bottom Right Of The Quad (Front)
00657 
00658   glNormal3f(0,0,-1);
00659   glVertex3f( lx,-ly,-lz);                        // Bottom Left Of The Quad (Back)
00660   glVertex3f(-lx,-ly,-lz);                        // Bottom Right Of The Quad (Back)
00661   glVertex3f(-lx, ly,-lz);                        // Top Right Of The Quad (Back)
00662   glVertex3f( lx, ly,-lz);                        // Top Left Of The Quad (Back)
00663 
00664   glNormal3f(-1,0,0);
00665   glVertex3f(-lx, ly, lz);                        // Top Right Of The Quad (Left)
00666   glVertex3f(-lx, ly,-lz);                        // Top Left Of The Quad (Left)
00667   glVertex3f(-lx,-ly,-lz);                        // Bottom Left Of The Quad (Left)
00668   glVertex3f(-lx,-ly, lz);                        // Bottom Right Of The Quad (Left)
00669 
00670   glNormal3f(1,0,0);
00671   glVertex3f( lx, ly,-lz);                        // Top Right Of The Quad (Right)
00672   glVertex3f( lx, ly, lz);                        // Top Left Of The Quad (Right)
00673   glVertex3f( lx,-ly, lz);                        // Bottom Left Of The Quad (Right)
00674   glVertex3f( lx,-ly,-lz);                        // Bottom Right Of The Quad (Right)
00675   glEnd();                                                          // Done Drawing The Quad
00676 
00677 }
00678 
00679 
00680 // This is recursively subdivides a triangular area (vertices p1,p2,p3) into
00681 // smaller triangles, and then draws the triangles. All triangle vertices are
00682 // normalized to a distance of 1.0 from the origin (p1,p2,p3 are assumed
00683 // to be already normalized). Note this is not super-fast because it draws
00684 // triangles rather than triangle strips.
00685 
00686 void ViewPort::drawPatch (double p1[3], double p2[3], double p3[3], int level)
00687 {
00688   int i;
00689   if (level > 0) {
00690     double q1[3],q2[3],q3[3];                 // sub-vertices
00691     for (i=0; i<3; i++) {
00692       q1[i] = 0.5f*(p1[i]+p2[i]);
00693       q2[i] = 0.5f*(p2[i]+p3[i]);
00694       q3[i] = 0.5f*(p3[i]+p1[i]);
00695     }
00696     double length1 = (double)(1.0/sqrt(q1[0]*q1[0]+q1[1]*q1[1]+q1[2]*q1[2]));
00697     double length2 = (double)(1.0/sqrt(q2[0]*q2[0]+q2[1]*q2[1]+q2[2]*q2[2]));
00698     double length3 = (double)(1.0/sqrt(q3[0]*q3[0]+q3[1]*q3[1]+q3[2]*q3[2]));
00699     for (i=0; i<3; i++) {
00700       q1[i] *= length1;
00701       q2[i] *= length2;
00702       q3[i] *= length3;
00703     }
00704     drawPatch (p1,q1,q3,level-1);
00705     drawPatch (q1,p2,q2,level-1);
00706     drawPatch (q1,q2,q3,level-1);
00707     drawPatch (q3,q2,p3,level-1);
00708   }
00709   else {
00710     glNormal3f (p1[0],p1[1],p1[2]);
00711     glVertex3f (p1[0],p1[1],p1[2]);
00712     glNormal3f (p2[0],p2[1],p2[2]);
00713     glVertex3f (p2[0],p2[1],p2[2]);
00714     glNormal3f (p3[0],p3[1],p3[2]);
00715     glVertex3f (p3[0],p3[1],p3[2]);
00716   }
00717 }
00718 
00719 // draw a sphere of radius 1
00720 
00721 void ViewPort::drawSphere()
00722 {
00723   // icosahedron data for an icosahedron of radius 1.0
00724 # define ICX 0.525731112119133606f
00725 # define ICZ 0.850650808352039932f
00726   static GLdouble idata[12][3] = {
00727     {-ICX, 0, ICZ},
00728     {ICX, 0, ICZ},
00729     {-ICX, 0, -ICZ},
00730     {ICX, 0, -ICZ},
00731     {0, ICZ, ICX},
00732     {0, ICZ, -ICX},
00733     {0, -ICZ, ICX},
00734     {0, -ICZ, -ICX},
00735     {ICZ, ICX, 0},
00736     {-ICZ, ICX, 0},
00737     {ICZ, -ICX, 0},
00738     {-ICZ, -ICX, 0}
00739   };
00740 
00741   static int index[20][3] = {
00742     {0, 4, 1},          {0, 9, 4},
00743     {9, 5, 4},          {4, 5, 8},
00744     {4, 8, 1},          {8, 10, 1},
00745     {8, 3, 10},   {5, 3, 8},
00746     {5, 2, 3},          {2, 7, 3},
00747     {7, 10, 3},   {7, 6, 10},
00748     {7, 11, 6},   {11, 0, 6},
00749     {0, 1, 6},          {6, 1, 10},
00750     {9, 0, 11},   {9, 11, 2},
00751     {9, 2, 5},          {7, 2, 11},
00752   };
00753 
00754   if (listnum==0) {
00755     listnum = glGenLists (1);
00756     glNewList (listnum,GL_COMPILE);
00757     glBegin (GL_TRIANGLES);
00758     for (int i=0; i<20; i++) {
00759       drawPatch (&idata[index[i][2]][0],&idata[index[i][1]][0],
00760           &idata[index[i][0]][0],sphere_quality);
00761     }
00762     glEnd();
00763     glEndList();
00764   }
00765   glCallList (listnum);
00766 }
00767 
00768 
00769 
00770 void ViewPort::drawSphereShadow (double px, double py, double pz, double radius)
00771 {
00772   // calculate shadow constants based on light vector
00773   static int init=0;
00774   static double len2,len1,scale;
00775   if (!init) {
00776     len2 = LIGHTX*LIGHTX + LIGHTY*LIGHTY;
00777     len1 = 1.0f/(double)sqrt(len2);
00778     scale = (double) sqrt(len2 + 1);
00779     init = 1;
00780   }
00781 
00782   // map sphere center to ground plane based on light vector
00783   px -= LIGHTX*pz;
00784   py -= LIGHTY*pz;
00785 
00786   const double kx = 0.96592582628907f;
00787   const double ky = 0.25881904510252f;
00788   double x=radius, y=0;
00789 
00790   glBegin (GL_TRIANGLE_FAN);
00791   for (int i=0; i<24; i++) {
00792     // for all points on circle, scale to elongated rotated shadow and draw
00793     double x2 = (LIGHTX*x*scale - LIGHTY*y)*len1 + px;
00794     double y2 = (LIGHTY*x*scale + LIGHTX*y)*len1 + py;
00795     glTexCoord2f (x2*ground_scale+ground_ofsx,y2*ground_scale+ground_ofsy);
00796     glVertex3f (x2,y2,0);
00797 
00798     // rotate [x,y] vector
00799     double xtmp = kx*x - ky*y;
00800     y = ky*x + kx*y;
00801     x = xtmp;
00802   }
00803   glEnd();
00804 }
00805 
00806 
00807 void ViewPort::drawTriangle (const double *v0, const double *v1, const double *v2, int solid)
00808 {
00809   float u[3],v[3],normal[3];
00810   u[0] = v1[0] - v0[0];
00811   u[1] = v1[1] - v0[1];
00812   u[2] = v1[2] - v0[2];
00813   v[0] = v2[0] - v0[0];
00814   v[1] = v2[1] - v0[1];
00815   v[2] = v2[2] - v0[2];
00816 
00817   normal[0] = (u[1]*v[2] - u[2]*v[1]);
00818   normal[1] = (u[2]*v[0] - u[0]*v[2]);
00819   normal[2] = (u[0]*v[1] - u[1]*v[0]);
00820 
00821   normalizeVector3 (normal);
00822 
00823   glBegin(solid ? GL_TRIANGLES : GL_LINE_STRIP);
00824   glNormal3fv (normal);
00825   glVertex3dv (v0);
00826   glVertex3dv (v1);
00827   glVertex3dv (v2);
00828   glEnd();
00829 }
00830 
00831 void ViewPort::drawTriangleD (const double *v0, const double *v1, const double *v2, int solid)
00832 {
00833   float u[3],v[3],normal[3];
00834   u[0] = double( v1[0] - v0[0] );
00835   u[1] = double( v1[1] - v0[1] );
00836   u[2] = double( v1[2] - v0[2] );
00837   v[0] = double( v2[0] - v0[0] );
00838   v[1] = double( v2[1] - v0[1] );
00839   v[2] = double( v2[2] - v0[2] );
00840 
00841   normal[0] = (u[1]*v[2] - u[2]*v[1]);
00842   normal[1] = (u[2]*v[0] - u[0]*v[2]);
00843   normal[2] = (u[0]*v[1] - u[1]*v[0]);
00844 
00845   normalizeVector3 (normal);
00846 
00847   glBegin(solid ? GL_TRIANGLES : GL_LINE_STRIP);
00848   glNormal3fv (normal);
00849   glVertex3dv (v0);
00850   glVertex3dv (v1);
00851   glVertex3dv (v2);
00852   glEnd();
00853 }
00854 
00855 
00856 // draw a capped cylinder of length l and radius r, aligned along the x axis
00857 
00858 void ViewPort::drawCappedCylinder (double l, double r)
00859 {
00860   int i,j;
00861   double tmp,nx,ny,nz,start_nx,start_ny,a,ca,sa;
00862   // number of sides to the cylinder (divisible by 4):
00863   const int n = capped_cylinder_quality*4;
00864 
00865   l *= 0.5;
00866   a = double(M_PI*2.0)/double(n);
00867   sa = (double) sin(a);
00868   ca = (double) cos(a);
00869 
00870   // draw cylinder body
00871   ny=1; nz=0;                  // normal vector = (0,ny,nz)
00872   glBegin (GL_TRIANGLE_STRIP);
00873   for (i=0; i<=n; i++) {
00874     glNormal3d (ny,nz,0);
00875     glVertex3d (ny*r,nz*r,l);
00876     glNormal3d (ny,nz,0);
00877     glVertex3d (ny*r,nz*r,-l);
00878     // rotate ny,nz
00879     tmp = ca*ny - sa*nz;
00880     nz = sa*ny + ca*nz;
00881     ny = tmp;
00882   }
00883   glEnd();
00884 
00885   // draw first cylinder cap
00886   start_nx = 0;
00887   start_ny = 1;
00888   for (j=0; j<(n/4); j++) {
00889     // get start_n2 = rotated start_n
00890     double start_nx2 =  ca*start_nx + sa*start_ny;
00891     double start_ny2 = -sa*start_nx + ca*start_ny;
00892     // get n=start_n and n2=start_n2
00893     nx = start_nx; ny = start_ny; nz = 0;
00894     double nx2 = start_nx2, ny2 = start_ny2, nz2 = 0;
00895     glBegin (GL_TRIANGLE_STRIP);
00896     for (i=0; i<=n; i++) {
00897       glNormal3d (ny2,nz2,nx2);
00898       glVertex3d (ny2*r,nz2*r,l+nx2*r);
00899       glNormal3d (ny,nz,nx);
00900       glVertex3d (ny*r,nz*r,l+nx*r);
00901       // rotate n,n2
00902       tmp = ca*ny - sa*nz;
00903       nz = sa*ny + ca*nz;
00904       ny = tmp;
00905       tmp = ca*ny2- sa*nz2;
00906       nz2 = sa*ny2 + ca*nz2;
00907       ny2 = tmp;
00908     }
00909     glEnd();
00910     start_nx = start_nx2;
00911     start_ny = start_ny2;
00912   }
00913 
00914   // draw second cylinder cap
00915   start_nx = 0;
00916   start_ny = 1;
00917   for (j=0; j<(n/4); j++) {
00918     // get start_n2 = rotated start_n
00919     double start_nx2 = ca*start_nx - sa*start_ny;
00920     double start_ny2 = sa*start_nx + ca*start_ny;
00921     // get n=start_n and n2=start_n2
00922     nx = start_nx; ny = start_ny; nz = 0;
00923     double nx2 = start_nx2, ny2 = start_ny2, nz2 = 0;
00924     glBegin (GL_TRIANGLE_STRIP);
00925     for (i=0; i<=n; i++) {
00926       glNormal3d (ny,nz,nx);
00927       glVertex3d (ny*r,nz*r,-l+nx*r);
00928       glNormal3d (ny2,nz2,nx2);
00929       glVertex3d (ny2*r,nz2*r,-l+nx2*r);
00930       // rotate n,n2
00931       tmp = ca*ny - sa*nz;
00932       nz = sa*ny + ca*nz;
00933       ny = tmp;
00934       tmp = ca*ny2- sa*nz2;
00935       nz2 = sa*ny2 + ca*nz2;
00936       ny2 = tmp;
00937     }
00938     glEnd();
00939     start_nx = start_nx2;
00940     start_ny = start_ny2;
00941   }
00942 
00943   glPopMatrix();
00944 }
00945 
00946 
00947 // draw a cylinder of length l and radius r, aligned along the z axis
00948 
00949 void ViewPort::drawCylinder (double l, double r, double zoffset)
00950 {
00951   int i;
00952   double tmp,ny,nz,a,ca,sa;
00953   const int n = 24;        // number of sides to the cylinder (divisible by 4)
00954 
00955   l *= 0.5;
00956   a = double(M_PI*2.0)/double(n);
00957   sa = (double) sin(a);
00958   ca = (double) cos(a);
00959 
00960   // draw cylinder body
00961   ny=1; nz=0;                  // normal vector = (0,ny,nz)
00962   glBegin (GL_TRIANGLE_STRIP);
00963   for (i=0; i<=n; i++) {
00964     glNormal3d (ny,nz,0);
00965     glVertex3d (ny*r,nz*r,l+zoffset);
00966     glNormal3d (ny,nz,0);
00967     glVertex3d (ny*r,nz*r,-l+zoffset);
00968     // rotate ny,nz
00969     tmp = ca*ny - sa*nz;
00970     nz = sa*ny + ca*nz;
00971     ny = tmp;
00972   }
00973   glEnd();
00974 
00975   // draw top cap
00976   glShadeModel (GL_FLAT);
00977   ny=1; nz=0;                  // normal vector = (0,ny,nz)
00978   glBegin (GL_TRIANGLE_FAN);
00979   glNormal3d (0,0,1);
00980   glVertex3d (0,0,l+zoffset);
00981   for (i=0; i<=n; i++) {
00982     if (i==1 || i==n/2+1)
00983       setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
00984     glNormal3d (0,0,1);
00985     glVertex3d (ny*r,nz*r,l+zoffset);
00986     if (i==1 || i==n/2+1)
00987       setColor (color[0],color[1],color[2],color[3]);
00988 
00989     // rotate ny,nz
00990     tmp = ca*ny - sa*nz;
00991     nz = sa*ny + ca*nz;
00992     ny = tmp;
00993   }
00994   glEnd();
00995 
00996   // draw bottom cap
00997   ny=1; nz=0;                  // normal vector = (0,ny,nz)
00998   glBegin (GL_TRIANGLE_FAN);
00999   glNormal3d (0,0,-1);
01000   glVertex3d (0,0,-l+zoffset);
01001   for (i=0; i<=n; i++) {
01002     if (i==1 || i==n/2+1)
01003       setColor (color[0]*0.75f,color[1]*0.75f,color[2]*0.75f,color[3]);
01004     glNormal3d (0,0,-1);
01005     glVertex3d (ny*r,nz*r,-l+zoffset);
01006     if (i==1 || i==n/2+1)
01007       setColor (color[0],color[1],color[2],color[3]);
01008 
01009     // rotate ny,nz
01010     tmp = ca*ny + sa*nz;
01011     nz = -sa*ny + ca*nz;
01012     ny = tmp;
01013   }
01014   glEnd();
01015 }
01016 
01017 //***************************************************************************
01018 // motion model
01019 
01020 // initialize the above variables
01021 
01022 void ViewPort::initMotionModel()
01023 {
01024   view_xyz[0] = 2;
01025   view_xyz[1] = 0;
01026   view_xyz[2] = 1;
01027   view_hpr[0] = 180;
01028   view_hpr[1] = 0;
01029   view_hpr[2] = 0;
01030 }
01031 
01032 
01033 void ViewPort::wrapCameraAngles()
01034 {
01035   for (int i=0; i<3; i++) {
01036     while (view_hpr[i] > 180) view_hpr[i] -= 360;
01037     while (view_hpr[i] < -180) view_hpr[i] += 360;
01038   }
01039 }
01040 
01041 
01042 // call this to update the current camera position. the bits in `mode' say
01043 // if the left (1), middle (2) or right (4) mouse button is pressed, and
01044 // (deltax,deltay) is the amount by which the mouse pointer has moved.
01045 
01046 void ViewPort::dsMotion (int mode, int deltax, int deltay)
01047 {
01048   double side = 0.01f * double(deltax);
01049   double fwd = (mode==4) ? (0.01f * double(deltay)) : 0.0f;
01050   double s = (double) sin (view_hpr[0]*DEG_TO_RAD);
01051   double c = (double) cos (view_hpr[0]*DEG_TO_RAD);
01052 
01053   LINFO("Movde %i", mode);
01054   switch(mode)
01055   {
01056     case 1:
01057       view_hpr[0] += double (deltax) * 0.5f;
01058       view_hpr[1] += double (deltay) * 0.5f;
01059       break;
01060     case 2:
01061     case 5:
01062      view_xyz[2] += 0.01f * double(deltay);
01063      view_hpr[2] += double (deltax) * 0.5f;
01064      break;
01065     case 4:
01066       view_xyz[0] += -s*side + c*fwd;
01067       view_xyz[1] += c*side + s*fwd;
01068       break;
01069 
01070   }
01071   wrapCameraAngles();
01072 
01073   LINFO("Camera pos:(%f,%f,%f) Rot:(%f,%f,%f)",
01074       view_xyz[0], view_xyz[1], view_xyz[2],
01075       view_hpr[0], view_hpr[1], view_hpr[2]);
01076 
01077 }
01078 
01079 //***************************************************************************
01080 // drawing loop stuff
01081 
01082 void ViewPort::drawSky (double view_xyz[3])
01083 {
01084   glDisable (GL_LIGHTING);
01085   if (use_textures && sky_texture->initialized()) {
01086     glEnable (GL_TEXTURE_2D);
01087     sky_texture->bind (0);
01088   }
01089   else {
01090     glDisable (GL_TEXTURE_2D);
01091     glColor3f (0,0.5,1.0);
01092   }
01093 
01094   // make sure sky depth is as far back as possible
01095   glShadeModel (GL_FLAT);
01096   glEnable (GL_DEPTH_TEST);
01097   glDepthFunc (GL_LEQUAL);
01098   glDepthRange (1,1);
01099 
01100   const double ssize = 1000.0f;
01101   static double offset = 0.0f;
01102 
01103   double x = ssize*sky_scale;
01104   double z = view_xyz[2] + sky_height;
01105 
01106   glBegin (GL_QUADS);
01107   glNormal3f (0,0,-1);
01108   glTexCoord2f (-x+offset,-x+offset);
01109   glVertex3f (-ssize+view_xyz[0],-ssize+view_xyz[1],z);
01110   glTexCoord2f (-x+offset,x+offset);
01111   glVertex3f (-ssize+view_xyz[0],ssize+view_xyz[1],z);
01112   glTexCoord2f (x+offset,x+offset);
01113   glVertex3f (ssize+view_xyz[0],ssize+view_xyz[1],z);
01114   glTexCoord2f (x+offset,-x+offset);
01115   glVertex3f (ssize+view_xyz[0],-ssize+view_xyz[1],z);
01116   glEnd();
01117 
01118   offset = offset + 0.001f;
01119   if (offset > 1) offset -= 1;
01120 
01121   glDepthFunc (GL_LESS);
01122   glDepthRange (0,1);
01123 }
01124 
01125 
01126 void ViewPort::drawGround()
01127 {
01128   glDisable (GL_LIGHTING);
01129   glShadeModel (GL_FLAT);
01130   glEnable (GL_DEPTH_TEST);
01131   glDepthFunc (GL_LESS);
01132   // glDepthRange (1,1);
01133 
01134   if (use_textures) {
01135     glEnable (GL_TEXTURE_2D);
01136     ground_texture->bind (0);
01137   }
01138   else {
01139     glDisable (GL_TEXTURE_2D);
01140     glColor3f (GROUND_R,GROUND_G,GROUND_B);
01141   }
01142 
01143   if (itsUseFog)
01144   {
01145     // ground fog seems to cause problems with TNT2 under windows
01146 
01147     GLfloat fogColor[4] = {0.0, 0.2, 0.1, 1};
01148     glEnable (GL_FOG);
01149     glFogi (GL_FOG_MODE, GL_LINEAR);
01150     glFogfv (GL_FOG_COLOR, fogColor);
01151     glFogf (GL_FOG_DENSITY, 0.07f);
01152     glHint (GL_FOG_HINT, GL_NICEST); // GL_DONT_CARE);
01153     glFogf (GL_FOG_START, 0.0);
01154     glFogf (GL_FOG_END, 10.0);
01155   }
01156 
01157 
01158   const double gsize = 100.0f;
01159   const double offset = 0; // -0.001f; ... polygon offsetting doesn't work well
01160 
01161   glBegin (GL_QUADS);
01162   glNormal3f (0,0,1);
01163 
01164   glTexCoord2f (-gsize*ground_scale + ground_ofsx,
01165       -gsize*ground_scale + ground_ofsy);
01166   glVertex3f (-gsize,-gsize,offset);
01167 
01168   glTexCoord2f (gsize*ground_scale + ground_ofsx,
01169       -gsize*ground_scale + ground_ofsy);
01170   glVertex3f (gsize,-gsize,offset);
01171 
01172   glTexCoord2f (gsize*ground_scale + ground_ofsx,
01173       gsize*ground_scale + ground_ofsy);
01174   glVertex3f (gsize,gsize,offset);
01175 
01176   glTexCoord2f (-gsize*ground_scale + ground_ofsx,
01177       gsize*ground_scale + ground_ofsy);
01178   glVertex3f (-gsize,gsize,offset);
01179   glEnd();
01180 
01181   //  if (itsUseFog)
01182   //    glDisable (GL_FOG);
01183 }
01184 
01185 
01186 void ViewPort::drawPyramidGrid()
01187 {
01188   // setup stuff
01189   glEnable (GL_LIGHTING);
01190   glDisable (GL_TEXTURE_2D);
01191   glShadeModel (GL_FLAT);
01192   glEnable (GL_DEPTH_TEST);
01193   glDepthFunc (GL_LESS);
01194 
01195   // draw the pyramid grid
01196   for (int i=-1; i<=1; i++) {
01197     for (int j=-1; j<=1; j++) {
01198       glPushMatrix();
01199       glTranslatef ((double)i,(double)j,(double)0);
01200       if (i==1 && j==0) setColor (1,0,0,1);
01201       else if (i==0 && j==1) setColor (0,0,1,1);
01202       else setColor (1,1,0,1);
01203       const double k = 0.03f;
01204       glBegin (GL_TRIANGLE_FAN);
01205       glNormal3f (0,-1,1);
01206       glVertex3f (0,0,k);
01207       glVertex3f (-k,-k,0);
01208       glVertex3f ( k,-k,0);
01209       glNormal3f (1,0,1);
01210       glVertex3f ( k, k,0);
01211       glNormal3f (0,1,1);
01212       glVertex3f (-k, k,0);
01213       glNormal3f (-1,0,1);
01214       glVertex3f (-k,-k,0);
01215       glEnd();
01216       glPopMatrix();
01217     }
01218   }
01219 }
01220 
01221 
01222 void ViewPort::dsDrawFrame (const double cameraParam[16])
01223 {
01224   glXMakeCurrent (display,win,glx_context);
01225   // setup stuff
01226   glEnable (GL_LIGHTING);
01227   glEnable (GL_LIGHT0);
01228   glDisable (GL_TEXTURE_2D);
01229   glDisable (GL_TEXTURE_GEN_S);
01230   glDisable (GL_TEXTURE_GEN_T);
01231   glShadeModel (GL_FLAT);
01232   glEnable (GL_DEPTH_TEST);
01233   glDepthFunc (GL_LESS);
01234   glEnable (GL_CULL_FACE);
01235   glCullFace (GL_BACK);
01236   glFrontFace (GL_CCW);
01237 
01238   if (itsWireframe)
01239     glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); //wireframe mode
01240 
01241   // setup viewport
01242   glMatrixMode(GL_MODELVIEW);
01243   glLoadIdentity();
01244 
01245   glViewport (0,0,itsWidth,itsHeight);
01246 
01247   glMatrixMode (GL_PROJECTION);
01248 
01249   if (itsProjMatrix==NULL) //Load from current view
01250   {
01251     glLoadIdentity();
01252     const double vnear = 50.1f;
01253     const double vfar = 5000.0f;
01254     const double k = itsZoomFactor;     // view scale, 1 = +/- 45 degrees
01255 
01256 
01257     if (itsWidth >= itsHeight) {
01258       double k2 = double(itsHeight)/double(itsWidth);
01259       glFrustum (-vnear*k,vnear*k,-vnear*k*k2,vnear*k*k2,vnear,vfar);
01260     }
01261     else {
01262       double k2 = double(itsWidth)/double(itsHeight);
01263       glFrustum (-vnear*k*k2,vnear*k*k2,-vnear*k,vnear*k,vnear,vfar);
01264     }
01265   } else { //Load the camera params
01266    glLoadMatrixd(itsProjMatrix);
01267   }
01268 
01269   // setup lights. it makes a difference whether this is done in the
01270   // GL_PROJECTION matrix mode (lights are scene relative) or the
01271   // GL_MODELVIEW matrix mode (lights are camera relative, bad!).
01272   static GLfloat light_ambient[] = { 0.2, 0.2, 0.2, 1.0 };
01273   static GLfloat light_diffuse[] = { 0.0, 0.0, 0.0, 0.0 };
01274   static GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
01275   glLightfv (GL_LIGHT0, GL_AMBIENT, light_ambient);
01276   glLightfv (GL_LIGHT0, GL_DIFFUSE, light_diffuse);
01277   glLightfv (GL_LIGHT0, GL_SPECULAR, light_specular);
01278   glColor3f (0.0, 0.0, 0.0);
01279 
01280   // clear the window
01281   glClearColor (0.0,0.0,0.0,0);
01282   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01283 
01284   // go to GL_MODELVIEW matrix mode and set the camera
01285   glMatrixMode (GL_MODELVIEW);
01286 
01287   if (cameraParam==NULL)
01288   {
01289     glLoadIdentity();
01290     setCamera (view_xyz[0],view_xyz[1],view_xyz[2],
01291         view_hpr[0],view_hpr[1],view_hpr[2]);
01292   } else {
01293     glLoadMatrixd(cameraParam );
01294   }
01295 
01296 
01297   // set the light position (for some reason we have to do this in model view.
01298   static GLfloat light_position[] = { LIGHTX, LIGHTY, 5.0 };
01299   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, light_position);
01300   glLightfv (GL_LIGHT0, GL_POSITION, light_position);
01301 
01302   // draw the background (ground, sky etc)
01303   if (itsDrawWorld)
01304   {
01305     drawSky (view_xyz);
01306     drawGround();
01307   }
01308 
01309   // draw the little markers on the ground
01310   //drawPyramidGrid();
01311 
01312   // leave openGL in a known state - flat shaded white, no textures
01313   glEnable (GL_LIGHTING);
01314   glDisable (GL_TEXTURE_2D);
01315   glShadeModel (GL_FLAT);
01316   glEnable (GL_DEPTH_TEST);
01317   glDepthFunc (GL_LESS);
01318   glColor3f (1,1,1);
01319   setColor (1,1,1,1);
01320 
01321   // draw the rest of the objects. set drawing state first.
01322   color[0] = 1;
01323   color[1] = 1;
01324   color[2] = 1;
01325   color[3] = 1;
01326   tnum = 0;
01327 }
01328 
01329 int ViewPort::dsGetShadows()
01330 {
01331   return use_shadows;
01332 }
01333 
01334 
01335 void ViewPort::dsSetShadows (int a)
01336 {
01337   use_shadows = (a != 0);
01338 }
01339 
01340 
01341 int ViewPort::dsGetTextures()
01342 {
01343   return use_textures;
01344 }
01345 
01346 
01347 void ViewPort::dsSetTextures (int a)
01348 {
01349   use_textures = (a != 0);
01350 }
01351 
01352 //***************************************************************************
01353 // C interface
01354 
01355 // sets lighting and texture modes, sets current color
01356 void ViewPort::setupDrawingMode()
01357 {
01358   glXMakeCurrent (display,win,glx_context);
01359 
01360   glEnable (GL_LIGHTING);
01361   bool enableWrap = true;
01362   if (tnum) {
01363     if (use_textures) {
01364       glEnable (GL_TEXTURE_2D);
01365 
01366       switch (tnum)
01367       {
01368         case SKY:
01369           sky_texture->bind (1);
01370           enableWrap = true;
01371           break;
01372         case GROUND:
01373           ground_texture->bind (1);
01374           enableWrap = true;
01375           break;
01376         case WOOD:
01377           wood_texture->bind (1);
01378           enableWrap = true;
01379           break;
01380         case TREE:
01381           tree_texture->bind (1);
01382           enableWrap = true;
01383           break;
01384         case OTHER:
01385           if (other_texture)
01386             other_texture->bind (1);
01387           //enableWrap = true;
01388           //glBindTexture(GL_TEXTURE_2D, tnum);
01389           enableWrap = false;
01390           break;
01391         default:
01392           LINFO("Unknown Texture %i", tnum);
01393           break;
01394       }
01395 
01396       if (enableWrap)
01397       {
01398         glEnable (GL_TEXTURE_GEN_S);
01399         glEnable (GL_TEXTURE_GEN_T);
01400         glTexGeni (GL_S,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
01401         glTexGeni (GL_T,GL_TEXTURE_GEN_MODE,GL_OBJECT_LINEAR);
01402         static GLfloat s_params[4] = {1.0f,1.0f,0.0f,1};
01403         static GLfloat t_params[4] = {0.817f,-0.817f,0.817f,1};
01404         glTexGenfv (GL_S,GL_OBJECT_PLANE,s_params);
01405         glTexGenfv (GL_T,GL_OBJECT_PLANE,t_params);
01406       }
01407     }
01408     else {
01409       glDisable (GL_TEXTURE_2D);
01410     }
01411   }
01412   else {
01413     glDisable (GL_TEXTURE_2D);
01414   }
01415   setColor (color[0],color[1],color[2],color[3]);
01416 
01417   if (color[3] < 1) {
01418     glEnable (GL_BLEND);
01419     glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
01420   }
01421   else {
01422     glDisable (GL_BLEND);
01423   }
01424 }
01425 
01426 
01427 void ViewPort::setShadowDrawingMode()
01428 {
01429   glDisable (GL_LIGHTING);
01430   if (use_textures) {
01431     glEnable (GL_TEXTURE_2D);
01432     ground_texture->bind (1);
01433     glColor3f (SHADOW_INTENSITY,SHADOW_INTENSITY,SHADOW_INTENSITY);
01434     glEnable (GL_TEXTURE_2D);
01435     glEnable (GL_TEXTURE_GEN_S);
01436     glEnable (GL_TEXTURE_GEN_T);
01437     glTexGeni (GL_S,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
01438     glTexGeni (GL_T,GL_TEXTURE_GEN_MODE,GL_EYE_LINEAR);
01439     static GLfloat s_params[4] = {(GLfloat)ground_scale,0,0,(GLfloat)ground_ofsx};
01440     static GLfloat t_params[4] = {0,(GLfloat)ground_scale,0,(GLfloat)ground_ofsy};
01441     glTexGenfv (GL_S,GL_EYE_PLANE,s_params);
01442     glTexGenfv (GL_T,GL_EYE_PLANE,t_params);
01443   }
01444   else {
01445     glDisable (GL_TEXTURE_2D);
01446     glColor3f (GROUND_R*SHADOW_INTENSITY,GROUND_G*SHADOW_INTENSITY,
01447         GROUND_B*SHADOW_INTENSITY);
01448   }
01449   glDepthRange (0,0.9999);
01450 }
01451 
01452 
01453 void ViewPort::dsSetViewpoint (double xyz[3], double hpr[3])
01454 {
01455   if (xyz) {
01456     view_xyz[0] = xyz[0];
01457     view_xyz[1] = xyz[1];
01458     view_xyz[2] = xyz[2];
01459   }
01460   if (hpr) {
01461     view_hpr[0] = hpr[0];
01462     view_hpr[1] = hpr[1];
01463     view_hpr[2] = hpr[2];
01464     wrapCameraAngles();
01465   }
01466 }
01467 
01468 
01469 void ViewPort::dsGetViewpoint (double xyz[3], double hpr[3])
01470 {
01471   if (xyz) {
01472     xyz[0] = view_xyz[0];
01473     xyz[1] = view_xyz[1];
01474     xyz[2] = view_xyz[2];
01475   }
01476   if (hpr) {
01477     hpr[0] = view_hpr[0];
01478     hpr[1] = view_hpr[1];
01479     hpr[2] = view_hpr[2];
01480   }
01481 }
01482 
01483 
01484 void ViewPort::dsSetTexture (TEXTURES texture_number, Texture* texturePtr)
01485 {
01486   tnum = texture_number;
01487   if (texturePtr)
01488     other_texture = texturePtr;
01489 }
01490 
01491 
01492 void ViewPort::dsSetColor (double red, double green, double blue)
01493 {
01494   color[0] = red;
01495   color[1] = green;
01496   color[2] = blue;
01497   color[3] = 1;
01498 }
01499 
01500 
01501 void ViewPort::dsSetColorAlpha (double red, double green, double blue,
01502     double alpha)
01503 {
01504   color[0] = red;
01505   color[1] = green;
01506   color[2] = blue;
01507   color[3] = alpha;
01508 }
01509 
01510 
01511 void ViewPort::dsDrawBox (const double pos[3], const double R[12],
01512     const double sides[3])
01513 {
01514 
01515   setupDrawingMode();
01516   glShadeModel (GL_FLAT);
01517   setTransform (pos,R);
01518   drawBox (sides);
01519   glPopMatrix();
01520 
01521   if (use_shadows) {
01522     setShadowDrawingMode();
01523     setShadowTransform();
01524     setTransform (pos,R);
01525     drawBox (sides);
01526     glPopMatrix();
01527     glPopMatrix();
01528     glDepthRange (0,1);
01529   }
01530 }
01531 
01532 
01533 void ViewPort::dsDrawSphere (const double pos[3], const double R[12],
01534     double radius)
01535 {
01536   setupDrawingMode();
01537   glEnable (GL_NORMALIZE);
01538   glShadeModel (GL_SMOOTH);
01539   setTransform (pos,R);
01540   glScaled (radius,radius,radius);
01541   drawSphere();
01542   glPopMatrix();
01543   glDisable (GL_NORMALIZE);
01544 
01545   // draw shadows
01546   if (use_shadows) {
01547     glDisable (GL_LIGHTING);
01548     if (use_textures) {
01549       ground_texture->bind (1);
01550       glEnable (GL_TEXTURE_2D);
01551       glDisable (GL_TEXTURE_GEN_S);
01552       glDisable (GL_TEXTURE_GEN_T);
01553       glColor3f (SHADOW_INTENSITY,SHADOW_INTENSITY,SHADOW_INTENSITY);
01554     }
01555     else {
01556       glDisable (GL_TEXTURE_2D);
01557       glColor3f (GROUND_R*SHADOW_INTENSITY,GROUND_G*SHADOW_INTENSITY,
01558           GROUND_B*SHADOW_INTENSITY);
01559     }
01560     glShadeModel (GL_FLAT);
01561     glDepthRange (0,0.9999);
01562     drawSphereShadow (pos[0],pos[1],pos[2],radius);
01563     glDepthRange (0,1);
01564   }
01565 }
01566 
01567 void ViewPort::dsDrawTriangle (const double pos[3], const double R[12],
01568     const double *v0, const double *v1,
01569     const double *v2, int solid)
01570 {
01571   setupDrawingMode();
01572   glShadeModel (GL_FLAT);
01573   setTransform (pos,R);
01574   drawTriangle (v0, v1, v2, solid);
01575   glPopMatrix();
01576 }
01577 
01578 
01579 void ViewPort::dsDrawCylinder (const double pos[3], const double R[12],
01580     double length, double radius)
01581 {
01582   setupDrawingMode();
01583   glShadeModel (GL_SMOOTH);
01584   setTransform (pos,R);
01585   drawCylinder (length,radius,0);
01586   glPopMatrix();
01587 
01588   if (use_shadows) {
01589     setShadowDrawingMode();
01590     setShadowTransform();
01591     setTransform (pos,R);
01592     drawCylinder (length,radius,0);
01593     glPopMatrix();
01594     glPopMatrix();
01595     glDepthRange (0,1);
01596   }
01597 }
01598 
01599 
01600 void ViewPort::dsDrawCappedCylinder (const double pos[3], const double R[12],
01601     double length, double radius)
01602 {
01603   setupDrawingMode();
01604   glShadeModel (GL_SMOOTH);
01605   setTransform (pos,R);
01606   drawCappedCylinder (length,radius);
01607   glPopMatrix();
01608 
01609   if (use_shadows) {
01610     setShadowDrawingMode();
01611     setShadowTransform();
01612     setTransform (pos,R);
01613     drawCappedCylinder (length,radius);
01614     glPopMatrix();
01615     glPopMatrix();
01616     glDepthRange (0,1);
01617   }
01618 }
01619 
01620 
01621 void ViewPort::dsDrawLine (const double pos1[3], const double pos2[3])
01622 {
01623   setupDrawingMode();
01624   glColor3f (color[0],color[1],color[2]);
01625   glDisable (GL_LIGHTING);
01626   glLineWidth (2);
01627   glShadeModel (GL_FLAT);
01628   glBegin (GL_LINES);
01629   glVertex3f (pos1[0],pos1[1],pos1[2]);
01630   glVertex3f (pos2[0],pos2[1],pos2[2]);
01631   glVertex3f (pos1[0],pos1[1],pos1[2]);
01632   glVertex3f (pos2[0],pos2[1],pos2[2]);
01633   glEnd();
01634 }
01635 
01636 
01637 void ViewPort::dsDrawBoxD (const double pos[3], const double R[12],
01638     const double sides[3])
01639 {
01640   int i;
01641   double pos2[3],R2[12],fsides[3];
01642   for (i=0; i<3; i++) pos2[i]=(double)pos[i];
01643   for (i=0; i<12; i++) R2[i]=(double)R[i];
01644   for (i=0; i<3; i++) fsides[i]=(double)sides[i];
01645   dsDrawBox (pos2,R2,fsides);
01646 }
01647 
01648 
01649 void ViewPort::dsDrawSphereD (const double pos[3], const double R[12], double radius)
01650 {
01651   int i;
01652   double pos2[3],R2[12];
01653   for (i=0; i<3; i++) pos2[i]=(double)pos[i];
01654   for (i=0; i<12; i++) R2[i]=(double)R[i];
01655   dsDrawSphere (pos2,R2,radius);
01656 }
01657 
01658 
01659 void ViewPort::dsDrawTriangleD (const double pos[3], const double R[12],
01660     const double *v0, const double *v1,
01661     const double *v2, int solid)
01662 {
01663   int i;
01664   double pos2[3],R2[12];
01665   for (i=0; i<3; i++) pos2[i]=(double)pos[i];
01666   for (i=0; i<12; i++) R2[i]=(double)R[i];
01667 
01668   setupDrawingMode();
01669   glShadeModel (GL_FLAT);
01670   setTransform (pos2,R2);
01671   drawTriangleD (v0, v1, v2, solid);
01672   glPopMatrix();
01673 }
01674 
01675 
01676 void ViewPort::dsDrawCylinderD (const double pos[3], const double R[12],
01677     double length, double radius)
01678 {
01679   int i;
01680   double pos2[3],R2[12];
01681   for (i=0; i<3; i++) pos2[i]=(double)pos[i];
01682   for (i=0; i<12; i++) R2[i]=(double)R[i];
01683   dsDrawCylinder (pos2,R2,length,radius);
01684 }
01685 
01686 
01687 void ViewPort::dsDrawCappedCylinderD (const double pos[3], const double R[12],
01688     double length, double radius)
01689 {
01690   int i;
01691   double pos2[3],R2[12];
01692   for (i=0; i<3; i++) pos2[i]=(double)pos[i];
01693   for (i=0; i<12; i++) R2[i]=(double)R[i];
01694   dsDrawCappedCylinder (pos2,R2,length,radius);
01695 }
01696 
01697 
01698 void ViewPort::dsDrawLineD (const double _pos1[3], const double _pos2[3])
01699 {
01700   int i;
01701   double pos1[3],pos2[3];
01702   for (i=0; i<3; i++) pos1[i]=(double)_pos1[i];
01703   for (i=0; i<3; i++) pos2[i]=(double)_pos2[i];
01704   dsDrawLine (pos1,pos2);
01705 }
01706 
01707 
01708 void ViewPort::dsSetSphereQuality (int n)
01709 {
01710   sphere_quality = n;
01711 }
01712 
01713 
01714 void ViewPort::dsSetCappedCylinderQuality (int n)
01715 {
01716   capped_cylinder_quality = n;
01717 }
01718 
01719 //THis function was obtained from a sample online.
01720 // http://www.spacesimulator.net/tut4_3dsloader.html
01721 // TODO rewrite this function
01722 ViewPort::DSObject ViewPort::load3DSObject(const char*filename, const char* textureFile)
01723 {
01724 
01725   DSObject p_object;
01726   int i; //Index variable
01727 
01728   //load the texture
01729   if (textureFile)
01730   {
01731     p_object.texture = new Texture(textureFile);
01732   } else {
01733     p_object.texture = NULL;
01734   }
01735 
01736 
01737 
01738   FILE *l_file; //File pointer
01739 
01740   unsigned short l_chunk_id; //Chunk identifier
01741   unsigned int l_chunk_lenght; //Chunk lenght
01742 
01743   unsigned char l_char; //Char variable
01744   unsigned short l_qty; //Number of elements in each chunk
01745 
01746   unsigned short l_face_flags; //Flag that stores some face information
01747 
01748   if ((l_file=fopen (filename, "rb"))== NULL)
01749   {
01750     LINFO("Can not open file %s", filename);
01751     return p_object; //Open the file
01752   }
01753 
01754   //Get the file length
01755   struct stat buf;
01756   fstat(fileno(l_file), &buf);
01757   long filelength = buf.st_size;
01758 
01759   while (ftell (l_file) < filelength) //Loop to scan the whole file
01760   {
01761     //getch(); //Insert this command for debug (to wait for keypress for each chuck reading)
01762 
01763     if(fread (&l_chunk_id, 2, 1, l_file) != 1) LFATAL("fread failed"); //Read the chunk header
01764     //printf("ChunkID: %x\n",l_chunk_id);
01765     if(fread (&l_chunk_lenght, 4, 1, l_file) != 1) LFATAL("fread failed"); //Read the lenght of the chunk
01766     //printf("ChunkLenght: %x\n",l_chunk_lenght);
01767 
01768     switch (l_chunk_id)
01769     {
01770       //----------------- MAIN3DS -----------------
01771       // Description: Main chunk, contains all the other chunks
01772       // Chunk ID: 4d4d
01773       // Chunk Lenght: 0 + sub chunks
01774       //-------------------------------------------
01775       case 0x4d4d:
01776         break;
01777 
01778         //----------------- EDIT3DS -----------------
01779         // Description: 3D Editor chunk, objects layout info
01780         // Chunk ID: 3d3d (hex)
01781         // Chunk Lenght: 0 + sub chunks
01782         //-------------------------------------------
01783       case 0x3d3d:
01784         break;
01785 
01786         //--------------- EDIT_OBJECT ---------------
01787         // Description: Object block, info for each object
01788         // Chunk ID: 4000 (hex)
01789         // Chunk Lenght: len(object name) + sub chunks
01790         //-------------------------------------------
01791       case 0x4000:
01792         i=0;
01793         do
01794         {
01795           if(fread (&l_char, 1, 1, l_file) != 1) LFATAL("fread faile");
01796           p_object.name[i]=l_char;
01797           i++;
01798         }while(l_char != '\0' && i<20);
01799         break;
01800 
01801         //--------------- OBJ_TRIMESH ---------------
01802         // Description: Triangular mesh, contains chunks for 3d mesh info
01803         // Chunk ID: 4100 (hex)
01804         // Chunk Lenght: 0 + sub chunks
01805         //-------------------------------------------
01806       case 0x4100:
01807         break;
01808 
01809         //--------------- TRI_VERTEXL ---------------
01810         // Description: Vertices list
01811         // Chunk ID: 4110 (hex)
01812         // Chunk Lenght: 1 x unsigned short (number of vertices)
01813         //             + 3 x float (vertex coordinates) x (number of vertices)
01814         //             + sub chunks
01815         //-------------------------------------------
01816       case 0x4110:
01817         if(fread (&l_qty, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed");
01818         p_object.vertices_qty = l_qty;
01819         //printf("Number of vertices: %d\n",l_qty);
01820         p_object.vertex.resize(l_qty);
01821         for (i=0; i<l_qty; i++)
01822         {
01823           if(fread (&p_object.vertex[i].x, sizeof(float), 1, l_file) != 1) LFATAL("fread failed");
01824           //printf("Vertices list x: %f\n",p_object.vertex[i].x);
01825           if(fread (&p_object.vertex[i].y, sizeof(float), 1, l_file) != 1) LFATAL("fread failed");
01826           //printf("Vertices list y: %f\n",p_object.vertex[i].y);
01827           if(fread (&p_object.vertex[i].z, sizeof(float), 1, l_file) != 1) LFATAL("fread failed");
01828           //printf("Vertices list z: %f\n",p_object.vertex[i].z);
01829         }
01830         break;
01831 
01832         //--------------- TRI_FACEL1 ----------------
01833         // Description: Polygons (faces) list
01834         // Chunk ID: 4120 (hex)
01835         // Chunk Lenght: 1 x unsigned short (number of polygons)
01836         //             + 3 x unsigned short (polygon points) x (number of polygons)
01837         //             + sub chunks
01838         //-------------------------------------------
01839       case 0x4120:
01840         if(fread (&l_qty, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed");
01841         p_object.polygons_qty = l_qty;
01842         p_object.polygon.resize(l_qty);
01843         printf("Number of polygons: %d\n",l_qty);
01844         for (i=0; i<l_qty; i++)
01845         {
01846           if(fread (&p_object.polygon[i].a, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed");
01847           //printf("Polygon point a: %d\n",p_object.polygon[i].a);
01848           if(fread (&p_object.polygon[i].b, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed");
01849           //printf("Polygon point b: %d\n",p_object.polygon[i].b);
01850           if(fread (&p_object.polygon[i].c, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed");
01851           //printf("Polygon point c: %d\n",p_object.polygon[i].c);
01852           if(fread (&l_face_flags, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed");
01853           //printf("Face flags: %x\n",l_face_flags);
01854         }
01855         break;
01856 
01857         //------------- TRI_MAPPINGCOORS ------------
01858         // Description: Vertices list
01859         // Chunk ID: 4140 (hex)
01860         // Chunk Lenght: 1 x unsigned short (number of mapping points)
01861         //             + 2 x float (mapping coordinates) x (number of mapping points)
01862         //             + sub chunks
01863         //-------------------------------------------
01864       case 0x4140:
01865         if(fread (&l_qty, sizeof (unsigned short), 1, l_file) != 1) LFATAL("fread failed");
01866         p_object.mapcoord.resize(l_qty);
01867         for (i=0; i<l_qty; i++)
01868         {
01869           if(fread (&p_object.mapcoord[i].u, sizeof (float), 1, l_file) != 1) LFATAL("fread failed");
01870           //printf("Mapping list u: %f\n",p_object.mapcoord[i].u);
01871           if(fread (&p_object.mapcoord[i].v, sizeof (float), 1, l_file) != 1) LFATAL("fread failed");
01872           //printf("Mapping list v: %f\n",p_object.mapcoord[i].v);
01873         }
01874         break;
01875 
01876         //----------- Skip unknow chunks ------------
01877         //We need to skip all the chunks that currently we don't use
01878         //We use the chunk lenght information to set the file pointer
01879         //to the same level next chunk
01880         //-------------------------------------------
01881       default:
01882         fseek(l_file, l_chunk_lenght-6, SEEK_CUR);
01883     }
01884   }
01885   fclose (l_file); // Closes the file stream
01886 
01887   return p_object;
01888 }
01889 
01890 
01891 int ViewPort::loadBitmap(const char*filename)
01892 {
01893   FILE * file;
01894   char temp;
01895   long i;
01896   int num_texture = 10;
01897 
01898   BITMAPINFOHEADER infoheader;
01899 
01900   if( (file = fopen(filename, "rb"))==NULL) return (-1); // Open the file for reading
01901 
01902   fseek(file, 18, SEEK_CUR);  /* start reading width & height */
01903   if(fread(&infoheader.biWidth, sizeof(int), 1, file) != 1) LFATAL("fread failed");
01904 
01905   if(fread(&infoheader.biHeight, sizeof(int), 1, file) != 1) LFATAL("fread failed");
01906 
01907   if(fread(&infoheader.biPlanes, sizeof(short int), 1, file) != 1) LFATAL("fread failed");
01908   if (infoheader.biPlanes != 1) {
01909     //printf("Planes from %s is not 1: %u\n", filename, infoheader.biPlanes);
01910     return 0;
01911   }
01912 
01913   // read the bpp
01914   if(fread(&infoheader.biBitCount, sizeof(unsigned short int), 1, file) != 1) LFATAL("fread failed");
01915   if (infoheader.biBitCount != 24) {
01916     //printf("Bpp from %s is not 24: %d\n", filename, infoheader.biBitCount);
01917     return 0;
01918   }
01919 
01920   fseek(file, 24, SEEK_CUR);
01921 
01922   // read the data.
01923   infoheader.data = (char *) malloc(infoheader.biWidth * infoheader.biHeight * 3);
01924   if (infoheader.data == NULL) {
01925     //printf("Error allocating memory for color-corrected image data\n");
01926     return 0;
01927   }
01928 
01929   if ((i = fread(infoheader.data, infoheader.biWidth * infoheader.biHeight * 3, 1, file)) != 1) {
01930     //printf("Error reading image data from %s.\n", filename);
01931     return 0;
01932   }
01933 
01934   for (i=0; i<(infoheader.biWidth * infoheader.biHeight * 3); i+=3) { // reverse all of the colors. (bgr -> rgb)
01935     temp = infoheader.data[i];
01936     infoheader.data[i] = infoheader.data[i+2];
01937     infoheader.data[i+2] = temp;
01938   }
01939 
01940 
01941   fclose(file); // Closes the file stream
01942 
01943 
01944   glBindTexture(GL_TEXTURE_2D, num_texture); // Bind the ID texture specified by the 2nd parameter
01945 
01946   // The next commands sets the texture parameters
01947   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // If the u,v coordinates overflow the range 0,1 the image is repeated
01948   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
01949   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // The magnification function ("linear" produces better results)
01950   glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); //The minifying function
01951 
01952   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // We don't combine the color with the original surface color, use only the texture map.
01953 
01954   // Finally we define the 2d texture
01955   glTexImage2D(GL_TEXTURE_2D, 0, 3, infoheader.biWidth, infoheader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, infoheader.data);
01956 
01957   // And create 2d mipmaps for the minifying function
01958 #ifdef INVT_HAVE_LIBGLUT
01959   gluBuild2DMipmaps(GL_TEXTURE_2D, 3, infoheader.biWidth, infoheader.biHeight, GL_RGB, GL_UNSIGNED_BYTE, infoheader.data);
01960 #endif
01961 
01962   free(infoheader.data); // Free the memory we used to load the texture
01963 
01964   return (num_texture); // Returns the current texture OpenGL ID
01965 }
01966 
01967 
01968 void ViewPort::dsDraw3DSObject(const double pos[3], const double R[12], DSObject& object)
01969 {
01970   if (object.texture != NULL)
01971     dsSetTexture (ViewPort::OTHER, object.texture);
01972 
01973   setupDrawingMode();
01974   glEnable (GL_NORMALIZE);
01975   glShadeModel (GL_SMOOTH);
01976 
01977   setTransform (pos,R);
01978   glScaled (object.scale,object.scale,object.scale);
01979   draw3dsObject(object);
01980   glPopMatrix();
01981   glDisable (GL_NORMALIZE);
01982 
01983 }
01984 
01985 void ViewPort::draw3dsObject(DSObject& object)
01986 {
01987   glBegin(GL_TRIANGLES); // glBegin and glEnd delimit the vertices that define a primitive (in our case triangles)
01988   //glBegin (GL_TRIANGLE_FAN);
01989   //glBegin (GL_TRIANGLE_STRIP);
01990   for (int l_index=0;l_index<object.polygons_qty;l_index++)
01991   {
01992     //----------------- FIRST VERTEX -----------------
01993     // Texture coordinates of the first vertex
01994     glTexCoord2f( object.mapcoord[ object.polygon[l_index].a ].u,
01995         object.mapcoord[ object.polygon[l_index].a ].v);
01996     // Coordinates of the first vertex
01997     glVertex3f( object.vertex[ object.polygon[l_index].a ].x,
01998         object.vertex[ object.polygon[l_index].a ].y,
01999         object.vertex[ object.polygon[l_index].a ].z); //Vertex definition
02000 
02001     //----------------- SECOND VERTEX -----------------
02002     // Texture coordinates of the second vertex
02003     glTexCoord2f( object.mapcoord[ object.polygon[l_index].b ].u,
02004         object.mapcoord[ object.polygon[l_index].b ].v);
02005     // Coordinates of the second vertex
02006     glVertex3f( object.vertex[ object.polygon[l_index].b ].x,
02007         object.vertex[ object.polygon[l_index].b ].y,
02008         object.vertex[ object.polygon[l_index].b ].z);
02009 
02010     //----------------- THIRD VERTEX -----------------
02011     // Texture coordinates of the third vertex
02012     glTexCoord2f( object.mapcoord[ object.polygon[l_index].c ].u,
02013         object.mapcoord[ object.polygon[l_index].c ].v);
02014     // Coordinates of the Third vertex
02015     glVertex3f( object.vertex[ object.polygon[l_index].c ].x,
02016         object.vertex[ object.polygon[l_index].c ].y,
02017         object.vertex[ object.polygon[l_index].c ].z);
02018   }
02019   glEnd();
02020   glFlush();
02021 
02022 }
Generated on Sun May 8 08:40:41 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3