Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Win32OpenGLDisplayDevice.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2008 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: Win32OpenGLDisplayDevice.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.98 $       $Date: 2008/03/27 19:36:50 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *   Subclass of DisplayDevice, this object has routines used by all the
00019  *   different display devices that are OpenGL-specific.  Will render drawing
00020  *   commands into a single window.
00021  ***************************************************************************/
00022 
00023 #if 1
00024 #ifndef _WIN32_WINNT
00025 #define _WIN32_WINNT 0x0400 // hack to allow access to mouse wheel events
00026 #endif
00027 #endif
00028 #include <windows.h>        // Mouse wheel events and related macros
00029 #include <winuser.h>        // Mouse wheel events and related macros
00030 
00031 #include "VMDApp.h"
00032 #include "OpenGLDisplayDevice.h"
00033 #include "Inform.h"
00034 #include "utilities.h"
00035 #include "config.h"   // VMD version strings etc
00036 
00037 #include <stdio.h>
00038 #include <stdlib.h>
00039 #include <math.h>
00040 #include <GL/gl.h>
00041 
00042 #include "../msvc/winvmd/res/resource.h" // VMD icon resource
00043 
00044 // NOTE: you may have to get copies of the latest OpenGL extension headers
00045 // from the OpenGL web site if your Linux or Win32 machine lacks them:
00046 //   http://oss.sgi.com/projects/ogl-sample/registry/
00047 #include <GL/glext.h>   // include OpenGL extension headers
00048 #include <GL/wglext.h>  // include OpenGL extension headers
00049 
00050 // static data for this object
00051 static const char *glStereoNameStr[OPENGL_STEREO_MODES] = 
00052  { "Off", 
00053    "CrystalEyes", 
00054    "CrystalEyesReversed", 
00055    "DTI SideBySide",
00056    "Scanline Interleaved",
00057    "Anaglyph",
00058    "CrossEyes", 
00059    "SideBySide", 
00060    "AboveBelow",
00061    "Left", 
00062    "Right" };
00063 
00064 static const char *glRenderNameStr[OPENGL_RENDER_MODES] =
00065 { "Normal",
00066   "AlphaBlend",
00067   "GLSL",
00068   "Acrobat3D" };
00069 
00070 static const char *glCacheNameStr[OPENGL_CACHE_MODES] = 
00071 { "Off",
00072   "On" };
00073 
00074 static char szAppName[] = "VMD";
00075 static char szAppTitle[]="VMD " VMDVERSION " OpenGL Display";
00076 static OpenGLDisplayDevice * ogldispdev; /* XXX HACK, GET RID OF GLOBALS!!! */
00077 
00078 LONG WINAPI vmdWindowProc( HWND, UINT, WPARAM, LPARAM );
00079 
00080 static int OpenWin32Connection(wgldata * glwsrv) {
00081   WNDCLASS  wc;
00082   HINSTANCE hInstance = GetModuleHandle(NULL);
00083 
00084   /* Clear (important!) and then fill in the window class structure. */
00085   memset(&wc, 0, sizeof(WNDCLASS));
00086   wc.style         = CS_OWNDC;
00087   wc.lpfnWndProc   = (WNDPROC) vmdWindowProc;
00088   wc.hInstance     = hInstance;
00089 #if 1
00090   // use our VMD icon
00091   wc.hIcon         = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
00092 #else
00093   wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
00094 #endif
00095   wc.hCursor       = LoadCursor(hInstance, IDC_ARROW);
00096   wc.hbrBackground = NULL; /* Default color */
00097   wc.lpszMenuName  = NULL;
00098   wc.lpszClassName = szAppName;
00099 
00100   if(!RegisterClass(&wc)) {
00101     printf("Cannot register window class.\n");
00102     return -1;
00103   }
00104 
00105   glwsrv->scrwidth  = GetSystemMetrics(SM_CXSCREEN);
00106   glwsrv->scrheight = GetSystemMetrics(SM_CYSCREEN);
00107 
00108   return 0;
00109 }
00110 
00111 static int PFDHasStereo(int ID, HDC hDC) {
00112   PIXELFORMATDESCRIPTOR pfd;
00113   DescribePixelFormat(hDC, ID, sizeof(PIXELFORMATDESCRIPTOR), &pfd); 
00114 
00115 #if 0
00116   // print a message if we find out we've got an accelerated mode
00117   if ((pfd.dwFlags & PFD_GENERIC_ACCELERATED) ||
00118       !(pfd.dwFlags & PFD_GENERIC_FORMAT))  
00119     msgInfo << "Hardware 3D Acceleration enabled." << sendmsg;
00120   else
00121     msgInfo << "No hardware 3D Acceleration found." << sendmsg;
00122 #endif
00123 
00124   if (pfd.dwFlags & PFD_STEREO) 
00125     return 1;
00126   
00127   return 0;
00128 } 
00129 
00130 #if 0
00131 static void PrintPFD(int ID, HDC hDC) {
00132   PIXELFORMATDESCRIPTOR pfd;
00133   FILE * ofp;
00134 
00135   if (ID == 0) {
00136     int i, num;
00137     num = DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), &pfd); 
00138     for (i=1; i<num; i++) 
00139       PrintPFD(i, hDC);
00140 
00141     return;
00142   }
00143 
00144   DescribePixelFormat(hDC, ID, sizeof(PIXELFORMATDESCRIPTOR), &pfd); 
00145 
00146   ofp=fopen("c:/video.txt", "a+");
00147   if (ofp == NULL) 
00148     ofp=stdout;
00149 
00150   if (pfd.cColorBits < 15) {
00151     fprintf(ofp, "Windows Pixel Format ID: %d -- not enough color bits\n", ID);
00152   }
00153   else {
00154     fprintf(ofp, "\nWindows Pixel Format ID: %d\n", ID);
00155     fprintf(ofp, "  Color Buffer Depth: %d bits\n", pfd.cColorBits);
00156     fprintf(ofp, "      Z Buffer Depth: %d bits\n", pfd.cDepthBits);
00157     if (pfd.dwFlags & PFD_DOUBLEBUFFER)
00158       fprintf(ofp, "    PFD_DOUBLEBUFFER\n"); 
00159     if (pfd.dwFlags & PFD_STEREO)
00160       fprintf(ofp, "    PFD_STEREO\n"); 
00161     if (pfd.dwFlags & PFD_DRAW_TO_WINDOW)
00162       fprintf(ofp, "    PFD_DRAW_TO_WINDOW\n"); 
00163     if (pfd.dwFlags & PFD_SUPPORT_GDI)
00164       fprintf(ofp, "    PFD_SUPPORT_GDI\n"); 
00165     if (pfd.dwFlags & PFD_SUPPORT_OPENGL)
00166       fprintf(ofp, "    PFD_SUPPORT_OPENGL\n"); 
00167     if (pfd.dwFlags & PFD_SWAP_EXCHANGE) 
00168       fprintf(ofp, "    PFD_SWAP_EXCHANGE\n"); 
00169     if (pfd.dwFlags & PFD_SWAP_COPY) 
00170       fprintf(ofp, "    PFD_SWAP_COPY\n"); 
00171     if (pfd.dwFlags & PFD_SWAP_LAYER_BUFFERS) 
00172       fprintf(ofp, "    PFD_SWAP_LAYER_BUFFERS\n"); 
00173     if (pfd.dwFlags & PFD_GENERIC_ACCELERATED)
00174       fprintf(ofp, "    PFD_GENERIC_ACCELERATED\n"); 
00175     if (pfd.dwFlags & PFD_GENERIC_FORMAT)
00176       fprintf(ofp, "    PFD_GENERIC_FORMAT\n"); 
00177   } 
00178   if (ofp != NULL && ofp != stdout) 
00179     fclose(ofp);
00180 }
00181 #endif
00182 
00183 static HGLRC SetupOpenGL(wgldata *glwsrv) {
00184   int ID;
00185   HDC hDC;
00186   HGLRC hRC;
00187 
00188   PIXELFORMATDESCRIPTOR pfd = {
00189     sizeof (PIXELFORMATDESCRIPTOR), /* struct size      */
00190     1,                              /* Version number   */
00191     PFD_DRAW_TO_WINDOW      /* Flags, draw to a window, */
00192       | PFD_DOUBLEBUFFER    /* Requires Doublebuffer hw */
00193       | PFD_STEREO          /* we want stereo if possible */ 
00194       | PFD_SUPPORT_OPENGL, /* use OpenGL               */
00195     PFD_TYPE_RGBA,          /* RGBA pixel values        */
00196     16,                     /* 24-bit color             */
00197     0, 0, 0,                /* RGB bits & shift sizes.  */
00198     0, 0, 0,                /* Don't care about them    */
00199     0, 0,                   /* No alpha buffer info     */
00200     0, 0, 0, 0, 0,          /* No accumulation buffer   */
00201     16,                     /* depth buffer             */
00202     1,                      /* stencil buffer           */
00203     0,                      /* No auxiliary buffers     */
00204     PFD_MAIN_PLANE,         /* Layer type               */
00205     0,                      /* Reserved (must be 0)     */
00206     0,                      /* No layer mask            */
00207     0,                      /* No visible mask          */
00208     0                       /* No damage mask           */
00209   };
00210 
00211   hDC = GetDC(glwsrv->hWnd);
00212   ID = ChoosePixelFormat(hDC, &pfd);
00213 
00214   /*
00215    * catch errors here.
00216    * If ID is zero, then there's
00217    * something wrong... most likely the window's
00218    * style bits are incorrect (in CreateWindow() )
00219    * or OpenGL isn't installed on this machine
00220    */
00221 
00222   if (ID == 0) {
00223     printf("Error selecting OpenGL Pixel Format!!\n");
00224     return NULL;
00225   }
00226 
00227   glwsrv->PFDisStereo = PFDHasStereo(ID, hDC);
00228   //PrintPFD(ID, hDC);
00229   //printf("*** Setting Windows OpenGL Pixel Format to ID %d ***\n", ID); 
00230   SetPixelFormat( hDC, ID, &pfd );
00231 
00232   hRC = wglCreateContext(hDC);
00233   ReleaseDC(glwsrv->hWnd, hDC);
00234 
00235   return hRC;
00236 }
00237 
00238 static int myCreateWindow(wgldata * glwsrv,
00239                           int xpos, int ypos, int xs, int ys) {
00240   /* Create a main window for this application instance. */
00241   glwsrv->hWnd =
00242         CreateWindow(
00243               szAppName,          /* app name */
00244               szAppTitle,         /* Text for window title bar */
00245               WS_OVERLAPPEDWINDOW /* Window style */
00246                | WS_CLIPCHILDREN
00247                | WS_CLIPSIBLINGS, /* NEED THESE for OpenGL calls to work! */
00248               xpos, ypos,
00249               xs, ys,
00250               NULL,                  /* no parent window                */
00251               NULL,                  /* Use the window class menu.      */
00252               GetModuleHandle(NULL), /* This instance owns this window  */
00253               glwsrv                 /* We don't use any extra data     */
00254         );
00255 
00256   if (!glwsrv->hWnd) {
00257     printf("Couldn't Open Window!!\n");
00258     return -1;
00259   }
00260 
00261   glwsrv->hDC = GetDC(glwsrv->hWnd);
00262   wglMakeCurrent(glwsrv->hDC, glwsrv->hRC);
00263 
00264   /* Make the window visible & update its client area */
00265   ShowWindow(glwsrv->hWnd, SW_SHOW);   /* Show the window             */
00266   UpdateWindow(glwsrv->hWnd );         /* Sends WM_PAINT message      */
00267   DragAcceptFiles(glwsrv->hWnd, TRUE); /* Enable Drag & Drop messages */
00268 
00269   return 0;
00270 }
00271 
00272 static void vmd_transwin32mouse(OpenGLDisplayDevice * d, LPARAM l) {
00273   int x, y;
00274   x = LOWORD(l);
00275   y = HIWORD(l);
00276   if(x & 1 << 15) x -= (1 << 16); // handle mouse capture in negative range
00277   if(y & 1 << 15) y -= (1 << 16); // handle mouse capture in negative range
00278   d->glwsrv.MouseX = x;
00279   d->glwsrv.MouseY = (d->ySize) - y; // translate to coords VMD likes (GL-like)
00280 }
00281 
00282 
00283 #ifdef VMDSPACEWARE
00284 // Windows code to talk to Spaceball device
00285 static void vmd_setupwin32spaceball(wgldata *glwsrv) {
00286   SiOpenData oData;
00287   enum SpwRetVal res;
00288 
00289   // init the sball pointer to NULL by default, used to determine if we
00290   // had a healthy init later on.
00291   glwsrv->sball = NULL;
00292 
00293   switch (SiInitialize()) {
00294     case SPW_NO_ERROR:
00295       break;
00296 
00297     case SPW_DLL_LOAD_ERROR:
00298       msgInfo << "Spaceball driver not installed.  Spaceball interface disabled." << sendmsg;
00299       return;
00300 
00301     default:
00302       msgInfo << "Spaceball did not initialize properly.  Spaceball interface disabled." << sendmsg;
00303       return;
00304   }
00305 
00306   SiOpenWinInit(&oData, glwsrv->hWnd);            // init win platform data
00307   SiSetUiMode(glwsrv->sball, SI_UI_ALL_CONTROLS); // config softbutton display
00308 
00309   // actually start a connection to the device now that the UI mode
00310   // and window system data are setup.
00311   glwsrv->sball = SiOpen("VMD", SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &oData);
00312   if ((glwsrv->sball == NULL) || (glwsrv->sball == SI_NO_HANDLE)) {
00313     SiTerminate(); // shutdown spaceware input library
00314     msgInfo << "Spaceball is unresponsive.  Spaceball interface disabled." << sendmsg;
00315     glwsrv->sball = NULL; // NULL out the handle for sure.
00316     return;
00317   }
00318 
00319   res = SiBeep(glwsrv->sball, "CcCc"); // beep the spaceball
00320   if ((glwsrv->sball != NULL) && (glwsrv->sball != SI_NO_HANDLE))
00321     msgInfo << "Spaceball found, software interface initialized." << sendmsg;
00322 }
00323 
00324 static void vmd_closewin32spaceball(wgldata *glwsrv) {
00325   enum SpwRetVal res;
00326 
00327   if (glwsrv->sball != NULL) {
00328     res = SiClose(glwsrv->sball); // close spaceball device
00329     if (res != SPW_NO_ERROR) 
00330       msgInfo << "An error occured while shutting down the Spaceball device." << sendmsg;
00331 
00332     SiTerminate();          // shutdown spaceware input library
00333   }
00334 
00335   glwsrv->sball = NULL;   // NULL out the handle.
00336 }
00337 
00338 static int vmd_processwin32spaceballevent(wgldata *glwsrv, UINT msg, WPARAM wParam, LPARAM lParam) {
00339 
00340   if (glwsrv == NULL)
00341     return 0;
00342 
00343   if (glwsrv->sball == NULL) 
00344     return 0;  // no spaceball attached/running
00345  
00346   // Check to see if this message is a spaceball message
00347   SiGetEventWinInit(&glwsrv->spwedata, msg, wParam, lParam);
00348 
00349   if (SiGetEvent(glwsrv->sball, 0, &glwsrv->spwedata, &glwsrv->spwevent) == SI_IS_EVENT) {
00350     return 1;
00351   }
00352 
00353   return 0;
00354 }
00355 #endif
00356 
00357 
00358 LONG WINAPI vmdWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
00359   PAINTSTRUCT   ps; /* Paint structure. */
00360 
00361   // XXX this enum has to be replicated here since its otherwise 
00362   //     private to the DisplayDevice class and children.
00363   enum EventCodes { WIN_REDRAW, WIN_LEFT, WIN_MIDDLE, WIN_RIGHT,
00364                     WIN_WHEELUP, WIN_WHEELDOWN, WIN_MOUSEX, WIN_MOUSEY, 
00365                     WIN_KEYBD, WIN_NOEVENT };
00366   wgldata *glwsrv;
00367 
00368   // when VMD destroys its window data structures it is possible that
00369   // the window could still get messages briefly thereafter, this prevents
00370   // us from attempting to handle any messages when the VMD state that goes
00371   // with the window has already been destructed. (most notably when using
00372   // the spaceball..)  If we have a NULL pointer, let windows handle the
00373   // event for us using the default window proc.
00374   if (ogldispdev == NULL) 
00375     return DefWindowProc(hwnd, msg, wParam, lParam); 
00376  
00377   glwsrv = &ogldispdev->glwsrv;
00378 
00379 #ifdef VMDSPACEWARE
00380   // see if it is a spaceball event, if so do something about it.
00381   if (vmd_processwin32spaceballevent(glwsrv, msg, wParam, lParam))
00382     return 0; //
00383 #endif
00384 
00385   switch(msg) {
00386     case WM_CREATE:
00387       glwsrv->hWnd = hwnd;
00388       glwsrv->hRC = SetupOpenGL(glwsrv);
00389       glwsrv->WEvents = WIN_REDRAW;
00390       return 0;
00391 
00392     case WM_SIZE:
00393       wglMakeCurrent(glwsrv->hDC, glwsrv->hRC);
00394       ogldispdev->xSize = LOWORD(lParam);  // XXX hack!!
00395       ogldispdev->ySize = HIWORD(lParam);  // XXX hack!!
00396       ogldispdev->reshape();               // XXX hack!! 
00397       glViewport(0, 0, (GLsizei) ogldispdev->xSize, (GLsizei) ogldispdev->ySize);
00398       glwsrv->WEvents = WIN_REDRAW;
00399       return 0;
00400 
00401     case WM_CLOSE:
00402       PostQuitMessage(0);
00403       return 0;
00404 
00405     case WM_PAINT:
00406       BeginPaint(hwnd, &ps);
00407       EndPaint(hwnd, &ps);
00408       glwsrv->WEvents = WIN_REDRAW;
00409       return 0;
00410 
00411     case WM_KEYDOWN:
00412       glwsrv->KeyFlag = MapVirtualKey(wParam, 2); // map to ASCII
00413       glwsrv->WEvents = WIN_KEYBD;
00414       return 0;
00415 
00416     case WM_MOUSEMOVE:
00417       vmd_transwin32mouse(ogldispdev, lParam);
00418       glwsrv->MouseFlags = wParam;
00419       return 0;
00420 
00421     case WM_MOUSEWHEEL:
00422       {
00423         int zDelta = ((short) HIWORD(wParam));
00424         // XXX
00425         // zDelta is in positive or negative multiples of WHEEL_DELTA for
00426         // clicky type scroll wheels on existing mice, may need to
00427         // recode this for continuous wheels at some future point in time.
00428         // WHEEL_DELTA is 120 in current versions of Windows.
00429         // We only activate an event if the user moves the mouse wheel at
00430         // least half of WHEEL_DELTA, so that they don't do it by accident
00431         // all the time.
00432         if (zDelta > (WHEEL_DELTA / 2)) {
00433           glwsrv->WEvents = WIN_WHEELUP;
00434         } else if (zDelta < -(WHEEL_DELTA / 2)) {
00435           glwsrv->WEvents = WIN_WHEELDOWN;
00436         }
00437       }
00438       return 0;
00439 
00440     case WM_LBUTTONDOWN:
00441       SetCapture(hwnd);
00442       vmd_transwin32mouse(ogldispdev, lParam);
00443       glwsrv->MouseFlags = wParam;
00444       glwsrv->WEvents = WIN_LEFT;
00445       return 0;
00446 
00447     case WM_LBUTTONUP:
00448       vmd_transwin32mouse(ogldispdev, lParam);
00449       glwsrv->MouseFlags = wParam;
00450       glwsrv->WEvents = WIN_LEFT;
00451       if (!(glwsrv->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) 
00452         ReleaseCapture();
00453       return 0;
00454 
00455     case WM_MBUTTONDOWN:
00456       SetCapture(hwnd);
00457       vmd_transwin32mouse(ogldispdev, lParam);
00458       glwsrv->MouseFlags = wParam;
00459       glwsrv->WEvents = WIN_MIDDLE;
00460       return 0;
00461 
00462     case WM_MBUTTONUP:
00463       vmd_transwin32mouse(ogldispdev, lParam);
00464       glwsrv->MouseFlags = wParam;
00465       glwsrv->WEvents = WIN_MIDDLE;
00466       if (!(glwsrv->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) 
00467         ReleaseCapture();
00468       return 0;
00469 
00470     case WM_RBUTTONDOWN:
00471       SetCapture(hwnd);
00472       vmd_transwin32mouse(ogldispdev, lParam);
00473       glwsrv->MouseFlags = wParam;
00474       glwsrv->WEvents = WIN_RIGHT;
00475       return 0;
00476 
00477     case WM_RBUTTONUP:
00478       vmd_transwin32mouse(ogldispdev, lParam);
00479       glwsrv->MouseFlags = wParam;
00480       glwsrv->WEvents = WIN_RIGHT;
00481       if (!(glwsrv->MouseFlags & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) 
00482         ReleaseCapture();
00483       return 0;
00484 
00485     case WM_SETCURSOR:
00486       // We process the mouse cursor hit test codes here, they tell us
00487       // what part of the window we're over, which helps us set the cursor
00488       // to the correct style for sizing borders, moves, etc.
00489       switch (LOWORD(lParam)) {
00490         case HTBOTTOM:
00491         case HTTOP:
00492           SetCursor(LoadCursor(NULL, IDC_SIZENS));
00493           break;
00494 
00495         case HTLEFT:
00496         case HTRIGHT:
00497           SetCursor(LoadCursor(NULL, IDC_SIZEWE));
00498           break;
00499 
00500         case HTTOPRIGHT:
00501         case HTBOTTOMLEFT:
00502           SetCursor(LoadCursor(NULL, IDC_SIZENESW));
00503           break;
00504 
00505         case HTTOPLEFT:
00506         case HTBOTTOMRIGHT:
00507           SetCursor(LoadCursor(NULL, IDC_SIZENWSE));
00508           break;
00509 
00510         case HTCAPTION:
00511           SetCursor(LoadCursor(NULL, IDC_ARROW));
00512           break;
00513           
00514         case HTCLIENT:
00515         default:
00516           ogldispdev->set_cursor(glwsrv->cursornum);
00517       }
00518       return 0;
00519 
00520     // 
00521     // Handle Windows File Drag and Drop Operations  
00522     // This code needs to be linked against SHELL32.DLL
00523     // 
00524     // XXX needs to be finished.
00525     case WM_DROPFILES: 
00526       {
00527         char lpszFile[4096];
00528         UINT numfiles, fileindex, numc;
00529         HDROP hDropInfo = (HDROP)wParam;
00530         
00531         // Get the number of simultaneous dragged/dropped files.
00532         numfiles = DragQueryFile(hDropInfo, (DWORD)(-1), (LPSTR)NULL, 0);
00533   
00534         msgInfo << "Ignoring Drag and Drop operation, received " 
00535                 << ((int) numfiles) << " files:" << sendmsg;
00536 
00537         FileSpec spec;       
00538         for (fileindex=0; fileindex<numfiles; fileindex++) {
00539           // lpszFile: complete pathname with device, colon and backslashes
00540           numc = DragQueryFile(hDropInfo, fileindex, (char *) &lpszFile, 4096);
00541   
00542           // VMD loads the file(s) here, or queues them up in its own
00543           // list to decide how to cope with them.  Deciding how to deal
00544           // with these files is definitely the tricky part.
00545           msgInfo << "  File(" << ((int) fileindex) << "): " << lpszFile 
00546                   << " (numc=" << ((int) numc) << ")" << sendmsg;
00547 
00548           // attempt to load the file into a new molecule
00549           ogldispdev->vmdapp->molecule_load(-1, lpszFile, NULL, &spec);
00550         }  
00551         DragFinish(hDropInfo); // finish drop operation and release memory
00552       }
00553       return 0;
00554 
00555     default:
00556       return DefWindowProc(hwnd, msg, wParam, lParam);
00557   }
00558 
00559   return 0;
00560 }
00561 
00562 
00564 
00565 OpenGLDisplayDevice::OpenGLDisplayDevice() 
00566 : OpenGLRenderer("VMD " VMDVERSION " OpenGL Display") {
00567   ogldispdev = this; // XXX Hack, global pointer for handling messages etc.
00568 
00569   // set up data possible before opening window
00570   stereoNames = glStereoNameStr;
00571   stereoModes = OPENGL_STEREO_MODES;
00572 
00573   renderNames = glRenderNameStr;
00574   renderModes = OPENGL_RENDER_MODES;
00575 
00576   cacheNames = glCacheNameStr;
00577   cacheModes = OPENGL_CACHE_MODES;
00578 
00579   memset(&glwsrv, 0, sizeof(glwsrv));
00580   have_window = FALSE;
00581   screenX = screenY = 0;
00582   vmdapp = NULL;
00583 }
00584 
00585 // init ... open a window and set initial default values
00586 int OpenGLDisplayDevice::init(int argc, char **argv, VMDApp *app, int *size, int *loc) {
00587   vmdapp = app; // save VMDApp handle for use by drag-and-drop handlers
00588 
00589   // open the window
00590   if (open_window(name, size, loc, argc, argv) != 0) return FALSE;
00591   if (!have_window) return FALSE;
00592 
00593   // set flags for the capabilities of this display
00594   ext->hasmultisample = FALSE;      // no code for this extension yet
00595   ext->nummultisamples = 0;
00596   ext->hasglvideoresizesun = FALSE; // will likely never have this extension
00597 
00598   aaAvailable = FALSE;
00599   cueingAvailable = TRUE;
00600   cullingAvailable = TRUE;
00601   cullingEnabled = FALSE;
00602 
00603   // set default settings
00604   cueing_off();
00605   culling_off();
00606   set_sphere_mode(sphereMode);
00607   set_sphere_res(sphereRes);
00608   set_line_width(lineWidth);
00609   set_line_style(lineStyle);
00610 
00611   // reshape and clear the display, which initializes some other variables
00612   reshape();
00613   normal();
00614   clear();
00615   update();
00616 
00617   // successfully created window
00618   return TRUE;
00619 }
00620 
00621 // destructor ... close the window
00622 OpenGLDisplayDevice::~OpenGLDisplayDevice(void) {
00623   if (have_window) {
00624     // close and delete windows, contexts, and display connections
00625     free_opengl_ctx(); // free display lists, textures, etc
00626 
00627 #if VMDSPACEWARE
00628     vmd_closewin32spaceball(&glwsrv);
00629 #endif
00630 
00631     ogldispdev = NULL; // XXX hack, global pointer for handling messages etc.
00632   }
00633 }
00634 
00635 
00637 
00638 // create a new window and set it's characteristics
00639 int OpenGLDisplayDevice::open_window(char *nm, int *size, int *loc,
00640                                         int argc, char** argv) {
00641   int SX = 596, SY = 190;
00642   if (loc) {
00643     SX = loc[0];
00644     // X screen uses Y increasing from upper-left corner down; this is
00645     // opposite to what GL does, which is the way VMD was set up originally
00646     SY = screenY - loc[1] - size[1];
00647   }
00648   glwsrv.cursornum = 0; // initialize cursor number
00649   
00650   // window opening stuff goes here
00651   int rc = OpenWin32Connection(&glwsrv);
00652   if (rc != 0) {
00653     return -1;
00654   }
00655 
00656   xOrig = 0;
00657   yOrig = 0;
00658   xSize = size[0]; 
00659   ySize = size[1]; 
00660   glwsrv.width = xSize; 
00661   glwsrv.height = ySize; 
00662   rc = myCreateWindow(&glwsrv, 0, 0, glwsrv.width, glwsrv.height);
00663   if (rc != 0) {
00664     return -1;
00665   }
00666 
00667   // Determine if stereo is available
00668   if (glwsrv.PFDisStereo == 0) {
00669     ext->hasstereo = FALSE;
00670   } else {
00671     ext->hasstereo = TRUE;
00672   }
00673   ext->stereodrawforced = FALSE; // don't force stereo draws initially
00674   
00675   setup_initial_opengl_state();
00676 
00677 #ifdef VMDSPACEWARE
00678   vmd_setupwin32spaceball(&glwsrv); 
00679 #endif
00680 
00681   // normal return: window was successfully created
00682   have_window = TRUE;
00683   // return window id
00684   return 0;
00685 }
00686 
00687 void OpenGLDisplayDevice::do_resize_window(int w, int h) {
00688   // add resize code here
00689 }
00690 
00691 void OpenGLDisplayDevice::do_reposition_window(int xpos, int ypos) {
00692   // add repositioning code here
00693 }
00694 
00695 
00697 
00698 //
00699 // get the current state of the device's pointer (i.e. cursor if it has one)
00700 //
00701 
00702 // abs X pos of cursor from lower-left corner of display
00703 int OpenGLDisplayDevice::x(void) {
00704   return glwsrv.MouseX;
00705 }
00706 
00707 // same, for Y direction
00708 int OpenGLDisplayDevice::y(void) {
00709   return glwsrv.MouseY;
00710 }
00711 
00712 // return the current state of the shift, control, and alt keys
00713 int OpenGLDisplayDevice::shift_state(void) {
00714   int retval = 0;
00715 
00716   if ((glwsrv.MouseFlags & MK_SHIFT) != 0)
00717     retval |= SHIFT;
00718   
00719   if ((glwsrv.MouseFlags & MK_CONTROL) != 0)
00720     retval |= CONTROL;
00721 
00722   return retval; 
00723 }
00724 
00725 // return the spaceball state, if any
00726 int OpenGLDisplayDevice::spaceball(int *rx, int *ry, int *rz, int *tx, int *ty, int *tz, int *buttons) {
00727 
00728 #ifdef VMDSPACEWARE
00729   if (glwsrv.sball != NULL) {
00730     *rx = glwsrv.spwevent.u.spwData.mData[SI_RX];
00731     *ry = glwsrv.spwevent.u.spwData.mData[SI_RY];
00732     *rz = glwsrv.spwevent.u.spwData.mData[SI_RZ];
00733     *tx = glwsrv.spwevent.u.spwData.mData[SI_TX];
00734     *ty = glwsrv.spwevent.u.spwData.mData[SI_TY];
00735     *tz = glwsrv.spwevent.u.spwData.mData[SI_TZ];
00736     *buttons = glwsrv.spwevent.u.spwData.bData.current;
00737     return 1;
00738   }
00739 #endif
00740 
00741   return 0;
00742 }
00743 
00744 
00745 // set the Nth cursor shape as the current one.
00746 void OpenGLDisplayDevice::set_cursor(int n) {
00747   glwsrv.cursornum = n; // hack to save cursor state when mouse enters/leaves
00748 
00749   switch (n) {
00750     default:
00751     case DisplayDevice::NORMAL_CURSOR:
00752       SetCursor(LoadCursor(NULL, IDC_ARROW));
00753       break;
00754 
00755     case DisplayDevice::TRANS_CURSOR:
00756       SetCursor(LoadCursor(NULL, IDC_SIZEALL));
00757       break;
00758  
00759     case DisplayDevice::SCALE_CURSOR:
00760       SetCursor(LoadCursor(NULL, IDC_SIZEWE));
00761       break;
00762 
00763     case DisplayDevice::PICK_CURSOR:
00764       SetCursor(LoadCursor(NULL, IDC_CROSS));
00765       break;
00766 
00767     case DisplayDevice::WAIT_CURSOR:
00768       SetCursor(LoadCursor(NULL, IDC_WAIT));
00769       break;
00770   }
00771 }
00772 
00773 
00774 //
00775 // event handling routines
00776 //
00777 
00778 // queue the standard events (need only be called once ... but this is
00779 // not done automatically by the window because it may not be necessary or
00780 // even wanted)
00781 void OpenGLDisplayDevice::queue_events(void) {
00782 }
00783 
00784 // read the next event ... returns an event type (one of the above ones),
00785 // and a value.  Returns success, and sets arguments.
00786 int OpenGLDisplayDevice::read_event(long &retdev, long &retval) {
00787   MSG msg;
00788 
00789   // This pumps the Windows message queue, forcing WEvents to be updated
00790   // by the time we return from DispatchMessage.
00791   if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
00792     TranslateMessage(&msg); // translate the message
00793     DispatchMessage(&msg);  // fire it off to the window proc
00794   } 
00795 
00796   retdev = glwsrv.WEvents;
00797 
00798   switch (glwsrv.WEvents) {
00799     case WIN_REDRAW:
00800       glwsrv.WEvents = WIN_NOEVENT;
00801       // reshape() is already called from within the window proc.
00802       _needRedraw = 1;
00803       return FALSE;
00804 
00805     case WIN_KEYBD:
00806       if (glwsrv.KeyFlag != '\0') {
00807         retval = glwsrv.KeyFlag;
00808         glwsrv.WEvents = WIN_NOEVENT;
00809         return TRUE;
00810       } else {
00811         break; 
00812       }
00813 
00814     case WIN_WHEELUP:
00815       retval = 1;
00816       glwsrv.WEvents = WIN_NOEVENT;
00817       return TRUE;
00818 
00819     case WIN_WHEELDOWN:
00820       retval = 1;
00821       glwsrv.WEvents = WIN_NOEVENT;
00822       return TRUE;
00823   
00824     case WIN_LEFT:
00825       // retval _must_ be either 1 or 0, nothing else...
00826       retval = (glwsrv.MouseFlags & MK_LBUTTON) != 0; 
00827       glwsrv.WEvents = WIN_NOEVENT;
00828       return TRUE;
00829 
00830     case WIN_MIDDLE:
00831       // retval _must_ be either 1 or 0, nothing else...
00832       retval = (glwsrv.MouseFlags & MK_MBUTTON) != 0; 
00833       glwsrv.WEvents = WIN_NOEVENT;
00834       return TRUE;
00835 
00836     case WIN_RIGHT:
00837       // retval _must_ be either 1 or 0, nothing else...
00838       retval = (glwsrv.MouseFlags & MK_RBUTTON) != 0; 
00839       glwsrv.WEvents = WIN_NOEVENT;
00840       return TRUE;
00841   }
00842 
00843   retval = 0; 
00844   glwsrv.WEvents = WIN_NOEVENT;
00845   return FALSE;
00846 }
00847 
00848 
00849 //
00850 // virtual routines for preparing to draw, drawing, and finishing drawing
00851 //
00852 
00853 // reshape the display after a shape change
00854 void OpenGLDisplayDevice::reshape(void) {
00855   // this code assumes that the xSize and ySize variables have
00856   // been updated (magically) already by the time this gets called.
00857 
00858   switch (inStereo) {
00859     case OPENGL_STEREO_SIDE:
00860     case OPENGL_STEREO_CROSSED:
00861       set_screen_pos(0.5f * (float)xSize / (float)ySize);
00862       break;
00863 
00864     case OPENGL_STEREO_ABOVEBELOW:
00865       set_screen_pos(2.0f * (float)xSize / (float)ySize);
00866       break;
00867 
00868     case OPENGL_STEREO_STENCIL:
00869       enable_stencil_stereo();
00870       set_screen_pos((float)xSize / (float)ySize);
00871       break;
00872  
00873     default:
00874       set_screen_pos((float)xSize / (float)ySize);
00875       break;
00876   }
00877 }
00878 
00879 unsigned char * OpenGLDisplayDevice::readpixels(int &x, int &y) {
00880   unsigned char * img;
00881 
00882   x = xSize;
00883   y = ySize;
00884 
00885   if ((img = (unsigned char *) malloc(x * y * 3)) != NULL) {
00886     glPixelStorei(GL_PACK_ALIGNMENT, 1);
00887     glReadPixels(0, 0, x, y, GL_RGB, GL_UNSIGNED_BYTE, img);
00888   } else {
00889     x = 0;
00890     y = 0;
00891   } 
00892 
00893   return img; 
00894 }
00895 
00896 
00897 // update after drawing
00898 void OpenGLDisplayDevice::update(int do_update) {
00899   glFlush();
00900 
00901   if(do_update) 
00902     SwapBuffers(glwsrv.hDC);
00903 
00904   glDrawBuffer(GL_BACK);
00905 }
00906 
00907 

Generated on Fri Sep 5 01:25:22 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002