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