Main Page   Class Hierarchy   Compound List   File List   Compound Members  

OpenGLWnd.cpp

00001 // OpenGLWnd.cpp : implementation file
00002 //
00003 
00004 #include "stdafx.h"
00005 #include "OpenGLWnd.h"
00006 #include "MainFrm.h"
00007 #include "VRMLFitToScreenTraverser.h"
00008 #include <gl\glaux.h>
00009 
00010 #include <assert.h>
00011 #include  <math.h>
00012 #include  <stdlib.h>
00013 
00014 #include <sys/timeb.h>
00015 #include <sys/types.h>
00016 
00017 #ifdef _DEBUG
00018 #define new DEBUG_NEW
00019 #undef THIS_FILE
00020 static char THIS_FILE[] = __FILE__;
00021 #endif
00022 
00023 /////////////////////////////////////////////////////////////////////////////
00024 // COpenGLWnd
00025 
00026         // -------------------------------------------------
00027         // My own code
00028         // -------------------------------------------------
00029 
00030 const int COpenGLWnd::mTIMER_RENDERING_INTERVAL = 20;
00031 const int COpenGLWnd::mTIMER_ROTATE_INTERVAL = 30;
00032 
00033 /**
00034 * Initialize the renderer with a VRMLModel to be rendered.
00035 * The VRMLRenderer is initialized, and the camera parameters are automatically adjusted to fit the model to screen.
00036 * The model is then added to the list of models to render. This function can be called several times with different
00037 * models in case more than one model is rendered. To remove the model from the renderer, use VRMLModelRenderer::RemoveModel()
00038 *
00039 * @param theModel the pointer to a VRMLModel to be added to the renderer
00040 *
00041 * @see VRMLModelRenderer
00042 * @see VRMLModelRenderer::RemoveModel()
00043 */
00044 void COpenGLWnd::Init(VRMLModel *theModel)
00045 {
00046         SetContext();
00047         BaseOGLVRMLModelRenderer::Init(theModel);
00048 
00049         glShadeModel(GL_SMOOTH);                                                        // Enable Smooth Shading
00050         
00051         glClearColor(0.0f, 0.0f, 0.0f, 0.5f);                           // Black Background
00052         glClearDepth(1.0f);                                                                     // Depth Buffer Setup
00053         glEnable(GL_DEPTH_TEST);                                                        // Enables Depth Testing
00054         glDepthFunc(GL_LEQUAL);                                                         // The Type Of Depth Testing To Do
00055         
00056         // glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   // Really Nice Perspective Calculations
00057         
00058         // For performance we set all of these to fastest.
00059         glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
00060         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
00061         glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);
00062         glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
00063         
00064         // Can't assume that normals aren't scaled. Therefore I need this.
00065         glEnable(GL_NORMALIZE);
00066         
00067         glEnable(GL_BLEND);
00068         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00069         // Reset modelview matrix before getting coords.
00070         glMatrixMode(GL_MODELVIEW);
00071         glLoadIdentity();
00072         
00073         // Retrieve max and min in all axes and also the worl-transformed coordinates in a vector.
00074         VRMLFitToScreenTraverser *tempFitter = new VRMLFitToScreenTraverser;
00075         
00076         tempFitter->Reset();
00077         theModel->traverse(theModel->rootNode, tempFitter);
00078         GLfloat sceneMinX, sceneMaxX, sceneMinY, sceneMaxY, sceneMinZ, sceneMaxZ;
00079         tempFitter->GetCoords(sceneMinX, sceneMaxX, sceneMinY, sceneMaxY, sceneMinZ, sceneMaxZ, mMaxRadius, mStoredVerts);
00080         
00081         GLfloat distance = (GLfloat)((mMaxRadius / 2.0) / mVGLR_PERSPECT_TAN_FOVY);
00082         
00083         // Make this constant.
00084         mFarPlane = distance * 10;
00085         
00086         mXTranslateFit = - (GLfloat)((sceneMinX + (abs(sceneMaxX - sceneMinX) / 2.0)));
00087         mYTranslateFit = - (GLfloat)((sceneMinY + (abs(sceneMaxY - sceneMinY) / 2.0)));
00088         mZTranslateFit = - (GLfloat)((distance + (abs(sceneMinZ - sceneMaxZ) / 2.0)));
00089         
00090         mXTranslate = mXTranslateFit;
00091         mYTranslate = mYTranslateFit;
00092         mZTranslate = mZTranslateFit;
00093         
00094         // Translate and zoom acceleration depends on size of model.
00095         mXAccel = (GLfloat)(fabs(sceneMinX - sceneMaxX) * 0.005);
00096         mYAccel = (GLfloat)(fabs(sceneMinX - sceneMaxX) * 0.005);
00097         mZAccel = (GLfloat)(fabs(sceneMinZ - sceneMaxZ) * 0.005);
00098         
00099         
00100         delete tempFitter;
00101         
00102         SetRenderingMode(mRenderingMode);
00103         
00104         if(mWindowWidth && mWindowHeight)
00105                 ReSizeGLScene(mWindowWidth, mWindowHeight);
00106         SwapGLBuffers();
00107 }
00108 
00109 
00110 /**
00111 * Render all attached VRML models to screen using OpenGL commands.
00112 * The actual rendering is implemented in VRMLRenderer, the parent class. 
00113 *
00114 * This function is called automatically by OnTimer() so only in special occassions it may
00115 * be interesting to call it directly. One such occassion is just after a textured model is loaded
00116 * in order to enforce loading of textures. In fact, when the VRMLModel is loaded from a file the
00117 * texture file names are stored but texture images are not actually loaded. This is done by the 
00118 * renderer when it renders the textured model first time. That can take some time, and it may be desirable
00119 * to call RenderToScreen() and thus force the loading of textures. The function will return after the
00120 * textures are loaded and the models rendered.
00121 */
00122 void COpenGLWnd::RenderToScreen()
00123 {
00124         static CMainFrame* pMainWnd = 0;
00125         struct _timeb timebuffer;
00126         
00127         _ftime( &timebuffer );
00128         
00129         long current_time = 1000 * timebuffer.time + timebuffer.millitm;
00130         static long last_times[50];
00131         static int cnt = -1;
00132 
00133 
00134         if(rendererBusy)   // a simple mechanism to make sure that we do not draw again before last rendering is done
00135         {
00136                 return;
00137         }
00138         rendererBusy = true;
00139 
00140         SetContext();
00141 
00142         
00143         
00144         if(cnt == -1)
00145         {
00146                 cnt = 0;
00147                 for(int i=0;i<10;i++)
00148                         last_times[i]=0;
00149         }
00150         cnt++;
00151         if(cnt == 50) cnt = 0;
00152         
00153         renderingFrameRate = 50000.0f / (float)(current_time - last_times[cnt]);
00154         
00155         last_times[cnt] = current_time;
00156         
00157         glMatrixMode(GL_MODELVIEW);
00158         if(modelViewMatrix)
00159         {
00160                 glLoadMatrixf(modelViewMatrix);
00161         }
00162         else
00163         {
00164                 glLoadIdentity();
00165                 
00166                 glTranslatef(mXTranslate, mYTranslate, mZTranslate);
00167                 glRotatef(mXRotAngle, 1.0f, 0.0f, 0.0f);
00168                 glRotatef(mYRotAngle, 0.0f, 1.0f, 0.0f);
00169         }
00170 
00171         BaseOGLVRMLModelRenderer::RenderToScreen();
00172         
00173         
00174         
00175         SwapGLBuffers();
00176 
00177         rendererBusy = false;
00178 
00179         // display the frame rate
00180         if(!pMainWnd) pMainWnd = (CMainFrame*)AfxGetMainWnd();
00181         char tmpmsg[100];
00182         sprintf(tmpmsg,"%2.2f FPS",renderingFrameRate);
00183         pMainWnd->m_wndStatusBar.SetPaneText( 0, tmpmsg, TRUE );
00184 }
00185 
00186 /**
00187 * Close down the renderer.
00188 * Tidy up and close the rendering system.
00189 */
00190 void COpenGLWnd::Close()
00191 {
00192         // Kill any pending timers.
00193         KillTimer(ID_ROTATE);
00194         
00195         SetContext();
00196 
00197         mXAccel = mYAccel = mZAccel = 0;
00198 
00199         mXTranslate = 0;
00200         mYTranslate = 0;
00201         mZTranslate = 0;
00202 
00203         mXRotAngle = 0;
00204         mYRotAngle = 0;
00205 
00206 
00207         BaseOGLVRMLModelRenderer::Close();
00208         SwapGLBuffers();
00209 }
00210 
00211         
00212         // -------------------------------------------------
00213         // VisualC++ added code below
00214         // -------------------------------------------------
00215 
00216 IMPLEMENT_DYNCREATE(COpenGLWnd, CView)
00217 
00218 COpenGLWnd::COpenGLWnd()
00219 {
00220         mLeftButtonDown = false;
00221         mRightButtonDown = false;
00222         m_bTimerSet = false;
00223         m_pDC = NULL;
00224         m_bSwap = true;
00225         bgtexture[0] = 0;
00226 
00227         mXTranslate = 0;
00228         mYTranslate = 0;
00229         mZTranslate = 0;
00230 
00231         mXRotAngle = 0;
00232         mYRotAngle = 0;
00233         // mZRotAngle = 0;
00234 
00235         mVGLR_PERSPECT_FOVY = 45.0f;
00236         mVGLR_PERSPECT_TAN_FOVY = tan(mVGLR_PERSPECT_FOVY / 2.0);
00237         mVGLR_PERSPECT_NEAR_PLANE = 0.1f;
00238         mFarPlane = 100.0f;
00239 
00240         mRenderingMode = VGLR_RENDERING_AS_IS;
00241 
00242         mBackfaceCull = true;
00243 
00244         modelViewMatrix = 0;
00245 }
00246 
00247 COpenGLWnd::~COpenGLWnd()
00248 {
00249         wglMakeCurrent(0,0);
00250         wglDeleteContext(m_hRC);
00251         if( m_pDC )
00252         {
00253                 delete m_pDC;
00254         }
00255 }
00256 
00257 // Standard OpenGL Init Stuff
00258 BOOL COpenGLWnd::SetupPixelFormat()
00259 {
00260         
00261   PIXELFORMATDESCRIPTOR pfdMain;
00262 
00263   memset( &pfdMain , 0 , sizeof( PIXELFORMATDESCRIPTOR ) );
00264   pfdMain.nSize = sizeof( PIXELFORMATDESCRIPTOR );
00265   pfdMain.nVersion = 1;
00266   pfdMain.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
00267   pfdMain.iPixelType = PFD_TYPE_RGBA;
00268   
00269         // Set to 16 for performance reasons.
00270         pfdMain.cColorBits = 16;
00271   pfdMain.cRedBits = 8;
00272   pfdMain.cRedShift = 16;
00273   pfdMain.cGreenBits = 8;
00274   pfdMain.cGreenShift = 8;
00275   pfdMain.cBlueBits = 8;
00276   pfdMain.cBlueShift = 0;
00277   pfdMain.cAlphaBits = 0;
00278   pfdMain.cAlphaShift = 0;
00279   pfdMain.cAccumBits = 64;
00280   pfdMain.cAccumRedBits = 16;
00281   pfdMain.cAccumGreenBits = 16;
00282   pfdMain.cAccumBlueBits = 16;
00283   pfdMain.cAccumAlphaBits = 0;
00284   pfdMain.cDepthBits = 32;
00285   pfdMain.cStencilBits = 8;
00286   pfdMain.cAuxBuffers = 0;
00287   pfdMain.iLayerType = PFD_MAIN_PLANE;
00288   pfdMain.bReserved = 0;
00289   pfdMain.dwLayerMask = 0;
00290   pfdMain.dwVisibleMask = 0;
00291   pfdMain.dwDamageMask = 0;
00292 
00293    // int m_nPixelFormat = ::ChoosePixelFormat( m_pDC->GetSafeHdc(), &pfdMain );
00294         int m_nPixelFormat = ::ChoosePixelFormat( m_pDC->GetSafeHdc(), &pfdMain );
00295 
00296     if ( m_nPixelFormat == 0 )
00297         return FALSE;
00298 
00299     // return ::SetPixelFormat( m_pDC->GetSafeHdc(), m_nPixelFormat, &pfdMain );
00300                 return ::SetPixelFormat( m_pDC->GetSafeHdc(), m_nPixelFormat, &pfdMain );
00301 }
00302 
00303 /**
00304 * Initialize OpenGL.
00305 * Perform necessary OpenGL initializations, including the startup of the rendering timer through StartRenderingTimer().
00306 */
00307 BOOL COpenGLWnd::InitOpenGL()
00308 {
00309         static init = 0;
00310 
00311         if(init) return true;
00312         init = 1;
00313 
00314         //Get a DC for the Client Area
00315         if (m_pDC != NULL) delete m_pDC;
00316         m_pDC = new CClientDC(this);
00317 
00318         //Failure to Get DC
00319         if( m_pDC == NULL )
00320                 return FALSE;
00321 
00322         if( !SetupPixelFormat() )
00323                 return FALSE;
00324 
00325         // Only one RC
00326         m_hRC = ::wglCreateContext( m_pDC->GetSafeHdc() );
00327 
00328     //Failure to Create Rendering Context
00329     if(m_hRC == 0 )
00330         return FALSE;
00331 
00332         //Make the RC Current
00333         if( ::wglMakeCurrent( m_pDC->GetSafeHdc(), m_hRC) == FALSE )
00334                 return FALSE;
00335 
00336         // REMOVE
00337         if( ::wglMakeCurrent( NULL, NULL ) == FALSE )
00338                         return FALSE;
00339 
00340         rendererBusy = false;
00341 
00342         StartRenderingTimer();
00343 
00344         return TRUE;
00345 }
00346 
00347 BEGIN_MESSAGE_MAP(COpenGLWnd, CView)
00348         //{{AFX_MSG_MAP(COpenGLWnd)
00349         ON_WM_CREATE()
00350         ON_WM_ERASEBKGND()
00351         ON_WM_SIZE()
00352         ON_WM_LBUTTONDOWN()
00353         ON_WM_RBUTTONDOWN()
00354         ON_WM_MOUSEMOVE()
00355         ON_WM_RBUTTONUP()
00356         ON_WM_TIMER()
00357         ON_WM_KEYDOWN()
00358         ON_WM_LBUTTONUP()
00359         //}}AFX_MSG_MAP
00360 END_MESSAGE_MAP()
00361 
00362 /////////////////////////////////////////////////////////////////////////////
00363 // COpenGLWnd drawing
00364 
00365 void COpenGLWnd::OnDraw(CDC* pDC)
00366 {
00367         RenderToScreen();
00368 }
00369 
00370 /////////////////////////////////////////////////////////////////////////////
00371 // COpenGLWnd diagnostics
00372 
00373 #ifdef _DEBUG
00374 void COpenGLWnd::AssertValid() const
00375 {
00376         CView::AssertValid();
00377 }
00378 
00379 void COpenGLWnd::Dump(CDumpContext& dc) const
00380 {
00381         CView::Dump(dc);
00382 }
00383 #endif //_DEBUG
00384 
00385 /////////////////////////////////////////////////////////////////////////////
00386 // COpenGLWnd message handlers
00387 
00388 
00389 /**
00390 * Initialize OpenGL when window is created.
00391 * 
00392 */
00393 int COpenGLWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
00394 {
00395         if (CView::OnCreate(lpCreateStruct) == -1)
00396                 return -1;
00397 
00398         if ( !InitOpenGL() )
00399         {
00400                 MessageBox( "Error setting up OpenGL!", "Init Error!",
00401                         MB_OK | MB_ICONERROR );
00402                 return -1;
00403         }
00404 
00405         return 0;
00406 }
00407 
00408 // Override the errase background function to
00409 // do nothing to prevent flashing.
00410 BOOL COpenGLWnd::OnEraseBkgnd(CDC* pDC) 
00411 {       
00412         return true;
00413 }
00414 
00415 // Set a few flags to make sure OpenGL only renders
00416 // in its viewport.
00417 BOOL COpenGLWnd::PreCreateWindow(CREATESTRUCT& cs) 
00418 {
00419         cs.style |= (WS_CLIPSIBLINGS | WS_CLIPCHILDREN | CS_OWNDC);
00420 
00421         cs.lpszClass = ::AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS,
00422           ::LoadCursor(NULL, IDC_ARROW), NULL, NULL);
00423                 
00424         return CView::PreCreateWindow(cs);
00425 }
00426 
00427 void COpenGLWnd::OnSize(UINT nType, int cx, int cy) 
00428 {
00429         CView::OnSize(nType, cx, cy);
00430         
00431         if ( 0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED )
00432                 return;
00433 
00434         SetContext();
00435 
00436         ReSizeGLScene(cx, cy);
00437 }
00438 
00439 void COpenGLWnd::OnLButtonDown(UINT nFlags, CPoint point) 
00440 {
00441                 if(nFlags & MK_CONTROL)
00442                         LeftButtonControlDown(point.x, point.y);
00443                 else
00444                         LeftButtonDown(point.x, point.y);
00445 
00446                 mLeftButtonDown = true;
00447 }
00448 
00449 void COpenGLWnd::OnRButtonDown(UINT nFlags, CPoint point) 
00450 {
00451                 RightButtonDown(point.x, point.y);      
00452                 mRightButtonDown = true;
00453 }
00454 
00455 void COpenGLWnd::OnMouseMove(UINT nFlags, CPoint point) 
00456 {
00457 
00458         if (!m_bTimerSet &&  mRightButtonDown) {
00459                 SetTimer(ID_ROTATE, mTIMER_ROTATE_INTERVAL, NULL);
00460                 m_bTimerSet = true;
00461                 return;
00462         }
00463         
00464                 if(nFlags & MK_LBUTTON)
00465                 {
00466                         // So we don't recieve events when user has not pressed anything.
00467                         if(!mLeftButtonDown) return;
00468                         
00469                         SetContext();
00470                         if(nFlags & MK_CONTROL)
00471                                 LeftButtonControlDrag(point.x, point.y);
00472                         else if(!(nFlags & MK_SHIFT))
00473                                 LeftButtonDrag(point.x, point.y);
00474                 }
00475                 else if (nFlags & MK_RBUTTON)
00476                 {
00477                         if(!mRightButtonDown) return;
00478                         RightButtonDrag(point.x, point.y);
00479                 }
00480         
00481 }
00482 
00483 void COpenGLWnd::OnRButtonUp(UINT nFlags, CPoint point) 
00484 {
00485                 KillTimer(ID_ROTATE);
00486                 m_bTimerSet = false;
00487                 mRightButtonDown = false;
00488 }
00489 
00490 /**
00491 * Start the rendering timer.
00492 * Start the timer for the rendering. After this, the OnTimer() function
00493 * is automatically called every mTIMER_RENDERING_INTERVAL milliseconds, and in turn it calls the render function. Thus we have
00494 * a rendering function call every mTIMER_RENDERING_INTERVAL milliseconds.
00495 */
00496 void COpenGLWnd::StartRenderingTimer()
00497 {
00498         SetTimer(ID_RENDERING, mTIMER_RENDERING_INTERVAL, NULL);
00499 }
00500 
00501 /**
00502 * Timer callback.
00503 * This function is called by the timer. This is used to implement the rendering cycle.
00504 */
00505 void COpenGLWnd::OnTimer(UINT nIDEvent) 
00506 {
00507         switch(nIDEvent)
00508         {
00509                 case ID_RENDERING:
00510                         RenderToScreen();
00511                         break;
00512                 case ID_ROTATE:
00513                         RightButtonDownTimerFunc();
00514                         break;
00515         }
00516 }
00517 
00518 void COpenGLWnd::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
00519 {
00520         SetContext();
00521                 if(nChar == VK_F1)
00522                         SetRenderingMode(VGLR_RENDERING_WIREFRAME);
00523                 else if(nChar == VK_F2)
00524                         SetRenderingMode(VGLR_RENDERING_AS_IS);
00525                 else if(nChar == VK_F11)
00526                         FitToScreen();
00527                 else
00528                         RenderToScreen();
00529         SwapGLBuffers();
00530 }
00531 
00532 void COpenGLWnd::OnLButtonUp(UINT nFlags, CPoint point) 
00533 {
00534         mLeftButtonDown = false;
00535 }
00536 
00537 
00538 /**
00539 * Pre-render setup function.
00540 * This function is called before the rendering in each rendering cycle. It sets up the GL context and clears the screen
00541 * to prepare for the next frame to be rendered. 
00542 *
00543 * This is a good place to insert the rendering of other objects in the scene,
00544 * background image or similar.
00545 */
00546 void COpenGLWnd::SetContext()
00547 { 
00548         // set the context
00549         wglMakeCurrent(m_pDC->GetSafeHdc(), m_hRC); 
00550         
00551         
00552         // clear the frame buffer before next drawing
00553         glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
00554         
00555         // INSERT CODE HERE TO RENDER ANY ADDITIONAL OBJECTS, BACKGROUND IMAGE OR SIMILAR
00556         DrawBackgroundImage();
00557 }
00558 
00559 int COpenGLWnd::LoadTexture(char *fullPath)
00560 {
00561 
00562         FILE *File=NULL;
00563         File=fopen(fullPath,"r");
00564 
00565         if(!File)
00566         {
00567                 return -1;
00568         }
00569         fclose(File);
00570 
00571         // Texture varible, return      
00572         GLuint texture[1];
00573 
00574 
00575         // Check file-extension
00576 //      if(fullPath.substr(fullPath.size() - 4, fullPath.size()) == temp)
00577         if(!strcmp(fullPath+(strlen(fullPath) - 4),".jpg"))
00578         {
00579                 glGenTextures(1, &texture[0]);                                  // Create The Texture
00580 
00581                 // Typical Texture Generation Using Data From The Bitmap
00582                 glBindTexture(GL_TEXTURE_2D, texture[0]);
00583 
00584                 JPEG_CORE_PROPERTIES *p = new JPEG_CORE_PROPERTIES;
00585 
00586                 if( ijlInit( p ) != IJL_OK ) return -1;
00587         
00588     p->JPGFile = fullPath;
00589 
00590                 // Read in params first so we get the right DIB.
00591     if( ijlRead( p, IJL_JFILE_READPARAMS ) != IJL_OK ) return -1;
00592     
00593     switch( p->JPGChannels )
00594     {
00595       case 1:  p->JPGColor    = IJL_G;
00596                p->DIBChannels = 3;
00597                p->DIBColor    = IJL_BGR;
00598                break;
00599       case 3:  p->JPGColor    = IJL_YCBCR;
00600                p->DIBChannels = 3;
00601                p->DIBColor    = IJL_BGR;
00602                break;
00603       case 4:  p->JPGColor    = IJL_YCBCRA_FPX;
00604                p->DIBChannels = 4;
00605                p->DIBColor    = IJL_RGBA_FPX;
00606                break;
00607       default: p->DIBColor = (IJL_COLOR)IJL_OTHER;
00608                p->JPGColor = (IJL_COLOR) IJL_OTHER;
00609                p->DIBChannels = p->JPGChannels;
00610                break;
00611     }
00612 
00613     p->DIBWidth    = p->JPGWidth;
00614     p->DIBHeight   = p->JPGHeight;
00615     p->DIBPadBytes = IJL_DIB_PAD_BYTES( p->DIBWidth, p->DIBChannels );
00616 
00617     int imageSize = p->DIBWidth * p->DIBChannels + p->DIBPadBytes;
00618     imageSize *= p->DIBHeight;
00619     p->DIBBytes = new BYTE[ imageSize ];
00620 
00621     if ( ijlRead( p, IJL_JFILE_READWHOLEIMAGE ) != IJL_OK ) return -1;
00622 
00623                 if ( p->DIBColor == IJL_RGBA_FPX )
00624                 {
00625       if ( p->DIBBytes )
00626           delete[] p->DIBBytes;
00627                         delete p;
00628                         return -1;
00629                 }
00630 
00631                 BYTE *flipImage = new BYTE[ imageSize ];
00632                 
00633                 // Flip the image - since library gives us upside down images.
00634                 int jMax = p->DIBWidth * p->DIBChannels + p->DIBPadBytes;
00635                 int iMax = p->DIBHeight;
00636 
00637                 for(int i=0; i < iMax; i++)
00638                         for(int j=0; j < jMax; j++)
00639                                 flipImage[i * jMax + j] = p->DIBBytes[((iMax - 1) - i) * jMax + j];
00640  
00641                 // Load texture into GL.
00642                 int maxSize = 0;
00643                 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
00644 
00645                 // Create a texture of nearest power 2
00646                 int xPowSize = 1;
00647                 int yPowSize = 1;
00648                 while((p->DIBWidth / xPowSize) > 0) xPowSize <<= 1;
00649                 while((p->DIBHeight / yPowSize) > 0) yPowSize <<= 1;
00650 
00651                 // Size to nearest lower power of 2 for speed
00652                 xPowSize >>= 1;
00653                 yPowSize >>= 1;
00654                 
00655                 // So we're not overriding gfx-cards capabilitys
00656                 if(xPowSize > maxSize) xPowSize = maxSize;
00657                 if(yPowSize > maxSize) yPowSize = maxSize;
00658 
00659                 // Allocate memory to the scaled image.
00660                 GLubyte* tempScaleImage = new GLubyte[yPowSize * (xPowSize * p->DIBChannels + p->DIBPadBytes)];
00661 
00662                 // Scale original image to nearest lower power of 2.
00663                 switch(p->DIBColor)
00664                 {
00665                         // Only three cases since last IJL_RGBA_FPX will never happen.
00666                         case IJL_RGB:
00667                                 {
00668                                         // gluScaleImage(GL_RGB, p->DIBWidth, p->DIBHeight, GL_UNSIGNED_BYTE, p->DIBBytes, xPowSize, yPowSize, GL_UNSIGNED_BYTE, tempScaleImage);
00669                                         gluScaleImage(GL_RGB, p->DIBWidth, p->DIBHeight, GL_UNSIGNED_BYTE, flipImage, xPowSize, yPowSize, GL_UNSIGNED_BYTE, tempScaleImage);
00670                                         // const GLubyte *ragga2 = gluErrorString(glGetError());
00671                         
00672                                         glTexImage2D(GL_TEXTURE_2D, 0, 3, xPowSize, yPowSize, 0, GL_RGB, GL_UNSIGNED_BYTE, tempScaleImage);
00673                                         // const GLubyte *ragga = gluErrorString(glGetError());
00674                                 }
00675                                 break;
00676 
00677                         case IJL_BGR:
00678                                 {
00679                                         gluScaleImage(GL_RGB, p->DIBWidth, p->DIBHeight, GL_UNSIGNED_BYTE, flipImage, xPowSize, yPowSize, GL_UNSIGNED_BYTE, tempScaleImage);
00680                                         // gluScaleImage(GL_BGR_EXT, p->DIBWidth, p->DIBHeight, GL_UNSIGNED_BYTE, p->DIBBytes, xPowSize, yPowSize, GL_UNSIGNED_BYTE, tempScaleImage);
00681                                         // const GLubyte *ragga2 = gluErrorString(glGetError());
00682 
00683                                         glTexImage2D(GL_TEXTURE_2D, 0, 3, xPowSize, yPowSize, 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, tempScaleImage);
00684                                         // const GLubyte *ragga = gluErrorString(glGetError());
00685                                 }
00686                                 break;
00687 
00688                         // Safety stuff.
00689                         default:
00690                                 return -1;
00691                                 break;
00692                 }
00693 
00694                 // Clean up
00695                 delete [] flipImage;
00696                 delete [] tempScaleImage;
00697                 delete [] p->DIBBytes;
00698                 delete p;
00699 
00700                 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
00701                 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
00702 
00703         }
00704         // Check file extension.
00705 //      else if(fullPath.substr(fullPath.size() - 4, fullPath.size()) == temp2)
00706         else if(!strcmp(fullPath+(strlen(fullPath) - 4),".bmp"))
00707         {
00708                 glGenTextures(1, &texture[0]);                                  // Create The Texture
00709 
00710                 // Typical Texture Generation Using Data From The Bitmap
00711                 glBindTexture(GL_TEXTURE_2D, texture[0]);
00712 
00713                 AUX_RGBImageRec *texPointer[1];
00714                 memset(texPointer,0,sizeof(void *)*1);
00715 
00716                 texPointer[0] = auxDIBImageLoad(fullPath);
00717 
00718                 glGenTextures(1, &texture[0]);                                  // Create The Texture
00719 
00720                 // Typical Texture Generation Using Data From The Bitmap
00721                 glBindTexture(GL_TEXTURE_2D, texture[0]);
00722 
00723                 int maxSize;
00724                 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
00725 
00726                 // Create a texture of nearest power 2
00727                 int xPowSize = 1;
00728                 int yPowSize = 1;
00729                 while((texPointer[0]->sizeX / xPowSize) > 0) xPowSize <<= 1;
00730                 while((texPointer[0]->sizeY / yPowSize) > 0) yPowSize <<= 1;
00731 
00732                 // Size to nearest lower power of 2 for speed
00733                 xPowSize >>= 1;
00734                 yPowSize >>= 1;
00735                 
00736                 // So we're not overriding gfx-cards capabilitys
00737                 if(xPowSize > maxSize) xPowSize = maxSize;
00738                 if(yPowSize > maxSize) yPowSize = maxSize;
00739 
00740                 GLubyte* tempScaleImage = new GLubyte[yPowSize * xPowSize * 3];
00741 
00742                 // Scale original image to nearest lower power of 2.
00743                 gluScaleImage(GL_RGB, texPointer[0]->sizeX, texPointer[0]->sizeY, GL_UNSIGNED_BYTE, texPointer[0]->data, xPowSize, yPowSize, GL_UNSIGNED_BYTE, tempScaleImage);
00744 
00745                 const GLubyte *ragga2 = gluErrorString(glGetError());
00746 
00747                 glTexImage2D(GL_TEXTURE_2D, 0, 3, xPowSize, yPowSize, 0, GL_RGB, GL_UNSIGNED_BYTE, tempScaleImage);
00748 
00749                 const GLubyte *ragga = gluErrorString(glGetError());
00750 
00751                 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Linear Filtering
00752                 glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // Linear Filtering
00753 
00754                 if (texPointer[0])                                                      // If Texture Exists
00755                 {
00756                         if (texPointer[0]->data)                                        // If Texture Image Exists
00757                         {
00758                                 free(texPointer[0]->data);                              // Free The Texture Image Memory
00759                                 delete [] tempScaleImage;
00760                         }
00761                         free(texPointer[0]);                                            // Free The Image Structure
00762                 }
00763         }
00764 
00765         // Successfully return the loaded image.
00766         return texture[0];
00767 }
00768 
00769 
00770 /**
00771 * Draw the background image on the screen.
00772 * Load the background image from the file background.jpg the first time this function is called.
00773 * If loading is succesful, the image is drawn on the screen every time the function is called.
00774 * This function is called by SetContext(), so it is executed at the beginning of every frame.
00775 *
00776 * @return true if image is succesfully drawn, 0 otherwise
00777 * @see SetContext()
00778 */
00779 bool COpenGLWnd::DrawBackgroundImage()
00780 {
00781         // draw the background image, if any
00782         static int noImage = 0;
00783 
00784         if(noImage)
00785                 return false;
00786 
00787 
00788 
00789         if(!bgtexture[0])
00790         {
00791                 bgtexture[0] = LoadTexture("background.jpg");
00792                 if(bgtexture[0] == -1)
00793                 {
00794                         noImage = 1;
00795                         return false;
00796                 }
00797         }
00798 
00799 
00800         glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_VIEWPORT_BIT | GL_ENABLE_BIT | GL_FOG_BIT | GL_STENCIL_BUFFER_BIT | GL_TRANSFORM_BIT | GL_TEXTURE_BIT );
00801         glDisable(GL_ALPHA_TEST);
00802         glDisable(GL_DEPTH_TEST);
00803         glDisable(GL_BLEND );
00804         glDisable(GL_DITHER);
00805         glDisable(GL_FOG);
00806         glDisable(GL_SCISSOR_TEST);
00807         glDisable(GL_STENCIL_TEST);
00808         glDisable(GL_LIGHTING);
00809         glDisable(GL_LIGHT0);
00810         glEnable(GL_TEXTURE_2D);
00811         glBindTexture(GL_TEXTURE_2D, bgtexture[0]);                             // Select Our Texture
00812 
00813         glMatrixMode(GL_MODELVIEW);
00814         glPushMatrix();
00815         glLoadIdentity();                                                                       // Reset The Projection Matrix
00816 
00817         
00818         glMatrixMode(GL_PROJECTION);
00819         glPushMatrix();
00820         glLoadIdentity();                                                                       // Reset The Projection Matrix
00821         glOrtho(0.0f,1.0f,0.0f,1.0f,-10.0f,10.0f);
00822 
00823         glBegin(GL_QUADS);
00824         glTexCoord2f(0.0f,0.0f);                
00825         glVertex3f(0.0f,0.0f,-5.0f);
00826 
00827         glTexCoord2f(1.0f,0.0f);                
00828         glVertex3f(1.0f,0.0f,-5.0f);
00829 
00830         glTexCoord2f(1.0f,1.0f);                
00831         glVertex3f(1.0f,1.0f,-5.0f);
00832 
00833         glTexCoord2f(0.0f,1.0f);                
00834         glVertex3f(0.0f,1.0f,-5.0f);
00835         
00836         glEnd();
00837         glPopMatrix();
00838         glMatrixMode(GL_MODELVIEW);
00839         glPopMatrix();
00840 
00841         glBindTexture(GL_TEXTURE_2D, 0);
00842         glPopAttrib();
00843         glClear(GL_DEPTH_BUFFER_BIT);
00844         return true;
00845 }
00846 
00847 
00848 
00849 
00850 
00851 
00852 
00853 
00854 
00855 
00856 
00857 
00858 
00859 
00860 
00861 
00862 
00863 
00864 
00865 
00866 
00867 void COpenGLWnd::ReSizeGLScene(GLsizei width, GLsizei height)           // Resize And Initialize The GL Window
00868 {
00869         if (height==0)                                                                          // Prevent A Divide By Zero By
00870         {
00871                 height=1;                                                                               // Making Height Equal One
00872         }
00873 
00874         mWindowWidth = width;
00875         mWindowHeight = height;
00876 
00877         glViewport(0,0,width,height);                                           // Reset The Current Viewport
00878 
00879         glMatrixMode(GL_PROJECTION);                                            // Select The Projection Matrix
00880         glLoadIdentity();                                                                       // Reset The Projection Matrix
00881 
00882         gluPerspective(mVGLR_PERSPECT_FOVY, (GLfloat)width/(GLfloat)height, mVGLR_PERSPECT_NEAR_PLANE, mFarPlane);
00883 
00884         glMatrixMode(GL_MODELVIEW);                                                     // Select The Modelview Matrix
00885 }
00886 
00887 
00888 void COpenGLWnd::SetModelViewMatrix(GLfloat *m)
00889 {
00890         modelViewMatrix = m;
00891 }
00892 
00893 
00894 void COpenGLWnd::ToggleBackfaceCull() 
00895 { 
00896         mBackfaceCull = !mBackfaceCull; 
00897         SetRenderingMode(mRenderingMode); 
00898 }
00899 
00900 void COpenGLWnd::SetRenderingMode(VGLR_RENDERING_MODE newMode)
00901 {
00902         switch(newMode)
00903         {
00904                 case VGLR_RENDERING_WIREFRAME:
00905                 {
00906                         // Set wireframe mode.
00907                         if(mBackfaceCull)
00908                                 glPolygonMode(GL_FRONT, GL_LINE);
00909                         else
00910                                 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00911                         
00912                         // Still want lighting tho..
00913                         glEnable(GL_LIGHTING);
00914                         glEnable(GL_LIGHT0);
00915 
00916                         // Material
00917                         glDisable(GL_COLOR_MATERIAL);
00918 
00919                         // Textures
00920                         glDisable(GL_TEXTURE_2D);
00921         
00922                         if(mBackfaceCull)
00923                         {
00924                                 glEnable(GL_CULL_FACE);
00925                                 glCullFace(GL_BACK);
00926                         }
00927                         else
00928                                 glDisable(GL_CULL_FACE);
00929                         
00930                 }
00931                 break;
00932 
00933                 case VGLR_RENDERING_SOLID_NO_MATERIAL:
00934                 {
00935                 }
00936                 break;
00937 
00938                 case VGLR_RENDERING_MATERIAL:
00939                 {
00940                 }
00941                 break;
00942 
00943                 case VGLR_RENDERING_AS_IS:
00944                 {
00945                         if(mBackfaceCull)
00946                                 glPolygonMode(GL_FRONT, GL_FILL);
00947                         else
00948                                 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00949 
00950                         // Lightning.
00951                         glEnable(GL_LIGHTING);
00952                         glEnable(GL_LIGHT0);
00953 
00954                         // Textures
00955                         glEnable(GL_TEXTURE_2D);
00956 
00957                         if(mBackfaceCull)
00958                         {
00959                                 glEnable(GL_CULL_FACE);
00960                                 glCullFace(GL_BACK);
00961                         }
00962                         else
00963                                 glDisable(GL_CULL_FACE);
00964                 }
00965                 break;
00966         }
00967 
00968         mRenderingMode = newMode;
00969 }
00970 
00971 
00972 void COpenGLWnd::LeftButtonDown(int x, int y)
00973 {
00974         mLeftButtonX = (GLfloat)x;
00975         mLeftButtonY = (GLfloat)y;
00976 }
00977 
00978 void COpenGLWnd::RightButtonDown(int x, int y)
00979 {
00980         mRightButtonX = (GLfloat)x;
00981         mRightButtonY = (GLfloat)y;
00982         mRotateXAngleAdd = 0;
00983         mRotateYAngleAdd = 0;
00984 
00985         // SetTimer(mhWnd, (UINT) IGLW_TIMER_ROTATE, 100, NULL);
00986         // SetCapture(mhWnd);
00987 }
00988 
00989 void COpenGLWnd::LeftButtonControlDown(int x, int y)
00990 {
00991         // Y gives the zoom factor in Z direction.
00992         mLeftButtonControlZ = (GLfloat)y;
00993 }
00994 
00995 void COpenGLWnd::LeftButtonDrag(int x, int y)
00996 {
00997 
00998         mXTranslate += (x - mLeftButtonX) * mXAccel;
00999 
01000         // Windows y-axis is reversed to openGL.
01001         mYTranslate -= (y - mLeftButtonY) * mYAccel;
01002 
01003         // Save off current position
01004         mLeftButtonX = (GLfloat)x;
01005         mLeftButtonY = (GLfloat)y;
01006 
01007         // Redraw screen.
01008         RenderToScreen();
01009 }
01010 
01011 void COpenGLWnd::RightButtonDrag(int x, int y)
01012 {
01013         // Rotates object around X or Y axis, distance from first point gives angular rotation speed.
01014         // Y axis rotation is given by distance in X coords, and vice versa.
01015         mRotateXAngleAdd = (GLfloat)((y - mRightButtonY) * 0.1);
01016         mRotateYAngleAdd = (GLfloat)((x - mRightButtonX) * 0.1);
01017 }
01018 
01019 void COpenGLWnd::LeftButtonControlDrag(int x, int y)
01020 {
01021         mZTranslate += (y - mLeftButtonControlZ) * mZAccel;
01022         mLeftButtonControlZ = (GLfloat)y;
01023 
01024         RenderToScreen();
01025 }
01026 
01027 void COpenGLWnd::RightButtonDownTimerFunc()
01028 {
01029         mXRotAngle += mRotateXAngleAdd;
01030         mYRotAngle += mRotateYAngleAdd;
01031 
01032         // Keep it within 360 degrees so that we don't get unpleasant surprises if datatype overflows. 
01033         if(mXRotAngle > 360.0f)
01034                 mXRotAngle -= 360.0f;
01035         if(mXRotAngle < 0.0f)
01036                 mXRotAngle += 360.0f;
01037         
01038         if(mYRotAngle > 360.0f)
01039                 mYRotAngle -= 360.0f;
01040         if(mYRotAngle < 0.0f)
01041                 mYRotAngle += 360.0f;
01042 
01043         RenderToScreen();
01044 }
01045 
01046 void COpenGLWnd::FitToScreen()
01047 {
01048         mXTranslate = mXTranslateFit;
01049         mYTranslate = mYTranslateFit;
01050         mZTranslate = mZTranslateFit;
01051         
01052         mXRotAngle = 0;
01053         mYRotAngle = 0;
01054 
01055         RenderToScreen();
01056 }
01057 
01058 void COpenGLWnd::FitToScreen(float zoom)
01059 {
01060         mXTranslate = mXTranslateFit;
01061         mYTranslate = mYTranslateFit;
01062         mZTranslate = mZTranslateFit * zoom;
01063         
01064         mXRotAngle = 0;
01065         mYRotAngle = 0;
01066 
01067         RenderToScreen();
01068 }

Generated on Wed Nov 8 16:13:38 2006 for VisageLink by doxygen 1.3.1