FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

winmain.C

Go to the documentation of this file.
00001 
00002 /*
00003  *        Polygon Reduction Demo by Stan Melax (c) 1998
00004  *  Permission to use any of this code wherever you want is granted..
00005  *  Although, please do acknowledge authorship if appropriate.
00006  *
00007  *  This module contains the window setup code, mouse input, timing
00008  *  routines, and that sort of stuff.  The interesting modules
00009  *  to see are bunnygut.cpp and progmesh.cpp.
00010  *
00011  *  The windows 95 specific code for this application was taken from
00012  *  an example of processing mouse events in an OpenGL program using
00013  *  the Win32 API from the www.opengl.org web site. 
00014  *  
00015  *  Under Project->Settings, Link Options, General Category
00016  *  Add:  
00017  *        Opengl32.lib glu32.lib winmm.lib 
00018  *  to the Object/Library Modules
00019  *  
00020  *  You will need have OpenGL libs and include files to compile this
00021  *  Go to the www.opengl.org web site if you need help with this.
00022  */
00023 
00024 
00025 #include <windows.h>    /* must include this before GL/gl.h */
00026 #include <GL/gl.h>      /* OpenGL header file */
00027 #include <GL/glu.h>     /* OpenGL utilities header file */
00028 #include <stdio.h>
00029 #include <sys/types.h>
00030 #include <sys/timeb.h>
00031 #include <time.h>
00032 
00033 #include "vector.h"
00034 #include "font.h"
00035 
00036 // Functions and Variables from bunny module
00037 extern void       InitModel();
00038 extern void       RenderModel();
00039 extern Vector     model_position;      // position of bunny 
00040 extern Quaternion model_orientation;   // orientation of bunny 
00041 
00042 // Global Variables
00043 float   DeltaT = 0.1f;
00044 float   FPS;
00045 int     Width  = 512;
00046 int     Height = 512;
00047 int     MouseX = 0;
00048 int     MouseY = 0;
00049 Vector  MouseVector;      // 3D direction mouse points
00050 Vector  OldMouseVector;
00051 int     MouseState=0;     // true iff left button down
00052 float   ViewAngle=45.0f;
00053 
00054 HDC hDC;                /* device context */
00055 HPALETTE hPalette = 0;  /* custom palette (if needed) */
00056 
00057 
00058 void CalcFPSDeltaT(){
00059     static int timeinit=0;
00060     static int start,start2,current,last;
00061     static int frame=0, frame2=0;
00062     if(!timeinit){
00063         frame=0;
00064         start=timeGetTime();
00065         timeinit=1;
00066     }
00067     frame++;
00068     frame2++;
00069     current=timeGetTime(); // found in winmm.lib
00070     double dif=(double)(current-start)/CLOCKS_PER_SEC;
00071     double rv = (dif)? (double)frame/(double)dif:-1.0;
00072     if(dif>2.0 && frame >10) {
00073         start  = start2;
00074         frame  = frame2;
00075         start2 = timeGetTime();
00076         frame2 = 0;
00077     }          
00078     DeltaT = (float)(current-last)/CLOCKS_PER_SEC;
00079     if(current==last) { 
00080         DeltaT = 0.1f/CLOCKS_PER_SEC;  // it just cant be 0
00081     }
00082     // if(DeltaT>1.0) DeltaT=1.0;
00083     FPS = (float)rv;
00084     last = current;
00085 }
00086 
00087 
00088 void ComputeMouseVector(){
00089     OldMouseVector=MouseVector;
00090     float spread = (float)tan(ViewAngle/2*3.14/180);  
00091     float y = spread * ((Height-MouseY)-Height/2.0f) /(Height/2.0f);
00092     float x = spread * (MouseX-Width/2.0f)  /(Height/2.0f);
00093     Vector v(x ,y,-1); 
00094     // v=UserOrientation *v;
00095     v=normalize(v);
00096     MouseVector = v;
00097 }
00098 
00099 Quaternion VirtualTrackBall(Vector cop,Vector cor,Vector dir1,Vector dir2) {
00100     // Implement track ball functionality to spin stuf on the screen
00101     //  cop   center of projection
00102     //  cor   center of rotation
00103     //  dir1  old mouse direction 
00104     //  dir2  new mouse direction
00105     // pretend there is a sphere around cor.  Then find the points
00106     // where dir1 and dir2 intersect that sphere.  Find the
00107     // rotation that takes the first point to the second.
00108     float m;
00109     // compute plane 
00110     Vector nrml = cor - cop;
00111     float fudgefactor = 1.0f/(magnitude(nrml) * 0.25f); // since trackball proportional to distance from cop
00112     nrml = normalize(nrml);
00113     float dist = -(nrml^cor);
00114     Vector u= planelineintersection(nrml,dist,cop,cop+dir1);
00115     u=u-cor;
00116     u=u*fudgefactor;
00117     m= magnitude(u);
00118     if(m>1) {u=u*1.0f/m;}
00119     else {
00120         u=u - (nrml * (float)sqrt(1-m*m));
00121     }
00122     Vector v= planelineintersection(nrml,dist,cop,cop+dir2);
00123     v=v-cor;
00124     v=v*fudgefactor;
00125     m= magnitude(v);
00126     if(m>1) {v=v*1.0f/m;}
00127     else {
00128         v=v - (nrml * (float)sqrt(1-m*m));
00129     }
00130     Vector axis = u*v;
00131     float angle;
00132     m=magnitude(axis);
00133     if(m>1)m=1; // avoid potential floating point error
00134     Quaternion q(Vector(1.0f,0.0f,0.0f),0.0f);
00135     if(m>0 && (angle=(float)asin(m))>3.14/180) {
00136             axis = normalize(axis);
00137             q=Quaternion(axis,angle);
00138     }
00139     return q;
00140 }
00141 
00142 void SpinIt(){
00143     // Change the orientation of the bunny according to mouse drag
00144     Quaternion q=VirtualTrackBall(Vector(0,0,0),model_position,
00145                                   OldMouseVector,MouseVector);
00146     model_orientation=q*model_orientation;
00147 }
00148 
00149 void Reshape(int width, int height){
00150     // called initially and when the window changes size
00151     Width=width;
00152     Height=height;
00153     glViewport(0, 0, width, height);
00154     glMatrixMode(GL_PROJECTION);
00155     glLoadIdentity();
00156     gluPerspective(ViewAngle, (float)width/height, 0.1, 50.0);
00157     glMatrixMode(GL_MODELVIEW);
00158     glLoadIdentity();
00159 }
00160 
00161 void PrintStats(){
00162     char buf[1024];buf[0]='\0';
00163     sprintf(buf,"FPS: %5.2f   ",FPS);
00164     PostString(buf,0,-1,0);
00165 }
00166 
00167 void Display(){
00168     // main drawing routine - called every frame
00169     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00170     glPushMatrix();
00171     glLoadIdentity();
00172     // camera at default (zero) position and orientation
00173     RenderModel();
00174     PrintStats();
00175     glLoadIdentity();
00176     RenderStrings();
00177     glPopMatrix();
00178     glFlush();
00179     SwapBuffers(hDC);           /* nop if singlebuffered */
00180 }
00181 
00182 
00183 LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
00184 { 
00185     static PAINTSTRUCT ps;
00186     static GLboolean left  = GL_FALSE;  /* left button currently down? */
00187     static GLboolean right = GL_FALSE;  /* right button currently down? */
00188     static int omx, omy, mx, my;
00189 
00190     switch(uMsg) {
00191     case WM_PAINT:
00192         BeginPaint(hWnd, &ps);
00193         EndPaint(hWnd, &ps);
00194         return 0;
00195     case WM_SIZE:
00196         Reshape(LOWORD(lParam), HIWORD(lParam));
00197         PostMessage(hWnd, WM_PAINT, 0, 0);
00198         return 0;
00199     case WM_CHAR:
00200         switch (wParam) {
00201             case 27: /* ESC key */
00202                 PostQuitMessage(0);
00203                 break;
00204         }
00205         return 0;
00206 
00207     case WM_LBUTTONDOWN:
00208         /* if we don't set the capture we won't get mouse move
00209            messages when the mouse moves outside the window. */
00210         SetCapture(hWnd);
00211         MouseX = LOWORD(lParam);
00212         MouseY = HIWORD(lParam);
00213         ComputeMouseVector();
00214         MouseState = 1;
00215         return 0;
00216 
00217     case WM_LBUTTONUP:
00218         MouseX = LOWORD(lParam);
00219         MouseY = HIWORD(lParam);
00220         if(MouseX & 1 << 15) MouseX -= (1 << 16);
00221         if(MouseY & 1 << 15) MouseY -= (1 << 16);
00222         ComputeMouseVector();
00223         if(MouseState) SpinIt();
00224         MouseState=0;
00225         /* remember to release the capture when we are finished. */
00226         ReleaseCapture();
00227         return 0;
00228 
00229     case WM_MOUSEMOVE:
00230         MouseX = LOWORD(lParam);
00231         MouseY = HIWORD(lParam);
00232         /* Win32 is pretty braindead about the x, y position that
00233            it returns when the mouse is off the left or top edge
00234            of the window (due to them being unsigned). therefore,
00235            roll the Win32's 0..2^16 pointer co-ord range to the
00236            more amenable (and useful) 0..+/-2^15. */
00237         if(MouseX & 1 << 15) MouseX -= (1 << 16);
00238         if(MouseY & 1 << 15) MouseY -= (1 << 16);
00239         ComputeMouseVector();
00240         if(MouseState) SpinIt();
00241         return 0;
00242 
00243     case WM_PALETTECHANGED:
00244         if (hWnd == (HWND)wParam) break;
00245         /* fall through to WM_QUERYNEWPALETTE */
00246     case WM_QUERYNEWPALETTE:
00247         if (hPalette) {
00248             UnrealizeObject(hPalette);
00249             SelectPalette(hDC, hPalette, FALSE);
00250             RealizePalette(hDC);
00251             return TRUE;
00252         }
00253         return FALSE;
00254 
00255     case WM_CLOSE:
00256         PostQuitMessage(0);
00257         return 0;
00258     }
00259     return DefWindowProc(hWnd, uMsg, wParam, lParam); 
00260 } 
00261 
00262 HWND CreateOpenGLWindow(char* title)
00263 {
00264     // make a double-buffered, rgba, opengl window
00265     int         n, pf;
00266     HWND        hWnd;
00267     WNDCLASS    wc;
00268     LOGPALETTE* lpPal;
00269     PIXELFORMATDESCRIPTOR pfd;
00270     static HINSTANCE hInstance = 0;
00271 
00272     /* only register the window class once - use hInstance as a flag. */
00273     if (!hInstance) {
00274         hInstance = GetModuleHandle(NULL);
00275         wc.style         = CS_OWNDC;
00276         wc.lpfnWndProc   = (WNDPROC)WindowProc;
00277         wc.cbClsExtra    = 0;
00278         wc.cbWndExtra    = 0;
00279         wc.hInstance     = hInstance;
00280         wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
00281         wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
00282         wc.hbrBackground = NULL;
00283         wc.lpszMenuName  = NULL;
00284         wc.lpszClassName = "OpenGL";
00285 
00286         if (!RegisterClass(&wc)) {
00287             MessageBox(NULL, "RegisterClass() failed:  "
00288                    "Cannot register window class.", "Error", MB_OK);
00289             return NULL;
00290         }
00291     }
00292 
00293     hWnd = CreateWindow("OpenGL", title, WS_OVERLAPPEDWINDOW |
00294             WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
00295             0,0,Width,Height, NULL, NULL, hInstance, NULL);
00296 
00297     if (hWnd == NULL) {
00298         MessageBox(NULL, "CreateWindow() failed:  Cannot create a window.",
00299                "Error", MB_OK);
00300         return NULL;
00301     }
00302 
00303     hDC = GetDC(hWnd);
00304 
00305     /* there is no guarantee that the contents of the stack that become
00306        the pfd are zeroed, therefore _make sure_ to clear these bits. */
00307     memset(&pfd, 0, sizeof(pfd));
00308     pfd.nSize        = sizeof(pfd);
00309     pfd.nVersion     = 1;
00310     pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
00311     pfd.iPixelType   = PFD_TYPE_RGBA;
00312     pfd.cDepthBits   = 32;
00313     pfd.cColorBits   = 32;
00314 
00315     pf = ChoosePixelFormat(hDC, &pfd);
00316     if (pf == 0) {
00317         MessageBox(NULL, "ChoosePixelFormat() failed:  "
00318                "Cannot find a suitable pixel format.", "Error", MB_OK); 
00319         return 0;
00320     } 
00321  
00322     if (SetPixelFormat(hDC, pf, &pfd) == FALSE) {
00323         MessageBox(NULL, "SetPixelFormat() failed:  "
00324                "Cannot set format specified.", "Error", MB_OK);
00325         return 0;
00326     } 
00327 
00328     DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
00329 
00330     if (pfd.dwFlags & PFD_NEED_PALETTE ||
00331         pfd.iPixelType == PFD_TYPE_COLORINDEX) {
00332 
00333         n = 1 << pfd.cColorBits;
00334         if (n > 256) n = 256;
00335 
00336         lpPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
00337                         sizeof(PALETTEENTRY) * n);
00338         memset(lpPal, 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * n);
00339         lpPal->palVersion = 0x300;
00340         lpPal->palNumEntries = n;
00341 
00342         GetSystemPaletteEntries(hDC, 0, n, &lpPal->palPalEntry[0]);
00343     
00344         /* if the pixel type is RGBA, then we want to make an RGB ramp,
00345            otherwise (color index) set individual colors. */
00346         if (pfd.iPixelType == PFD_TYPE_RGBA) {
00347             int redMask = (1 << pfd.cRedBits) - 1;
00348             int greenMask = (1 << pfd.cGreenBits) - 1;
00349             int blueMask = (1 << pfd.cBlueBits) - 1;
00350             int i;
00351 
00352             /* fill in the entries with an RGB color ramp. */
00353             for (i = 0; i < n; ++i) {
00354             lpPal->palPalEntry[i].peRed = 
00355                 (((i >> pfd.cRedShift)   & redMask)   * 255)/redMask;
00356             lpPal->palPalEntry[i].peGreen = 
00357                 (((i >> pfd.cGreenShift) & greenMask) * 255)/greenMask;
00358             lpPal->palPalEntry[i].peBlue = 
00359                 (((i >> pfd.cBlueShift)  & blueMask)  * 255)/blueMask;
00360             lpPal->palPalEntry[i].peFlags = 0;
00361             }
00362         } else {
00363             lpPal->palPalEntry[0].peRed = 0;
00364             lpPal->palPalEntry[0].peGreen = 0;
00365             lpPal->palPalEntry[0].peBlue = 0;
00366             lpPal->palPalEntry[0].peFlags = PC_NOCOLLAPSE;
00367             lpPal->palPalEntry[1].peRed = 255;
00368             lpPal->palPalEntry[1].peGreen = 0;
00369             lpPal->palPalEntry[1].peBlue = 0;
00370             lpPal->palPalEntry[1].peFlags = PC_NOCOLLAPSE;
00371             lpPal->palPalEntry[2].peRed = 0;
00372             lpPal->palPalEntry[2].peGreen = 255;
00373             lpPal->palPalEntry[2].peBlue = 0;
00374             lpPal->palPalEntry[2].peFlags = PC_NOCOLLAPSE;
00375             lpPal->palPalEntry[3].peRed = 0;
00376             lpPal->palPalEntry[3].peGreen = 0;
00377             lpPal->palPalEntry[3].peBlue = 255;
00378             lpPal->palPalEntry[3].peFlags = PC_NOCOLLAPSE;
00379         }
00380 
00381         hPalette = CreatePalette(lpPal);
00382         if (hPalette) {
00383             SelectPalette(hDC, hPalette, FALSE);
00384             RealizePalette(hDC);
00385         }
00386 
00387         free(lpPal);
00388     }
00389 
00390     ReleaseDC(hDC, hWnd);
00391     return hWnd;
00392 }    
00393 
00394 int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst,
00395     LPSTR lpszCmdLine, int nCmdShow)
00396 {
00397     HGLRC hRC;              /* opengl context */
00398     HWND  hWnd;             /* window */
00399     MSG   msg;              /* message */
00400 
00401     // InitModel() initializes some data structures and
00402     // does the progressive mesh polygon reduction algorithm
00403     // on the model.
00404     CalcFPSDeltaT(); // to time the algorithm
00405     InitModel();
00406     CalcFPSDeltaT();
00407 
00408     hWnd = CreateOpenGLWindow("bunnylod by Stan Melax");
00409     if (hWnd == NULL) exit(1);
00410 
00411     hDC = GetDC(hWnd);
00412     hRC = wglCreateContext(hDC);
00413     wglMakeCurrent(hDC, hRC);
00414     ShowWindow(hWnd, nCmdShow);
00415     glEnable(GL_DEPTH_TEST);
00416 
00417     PostString("Demo by Stan Melax (c)1998",5,-5,20);
00418     PostString("Model by Viewpoint Datalabs (c)1996",5,-4,20);
00419     char buf[128];
00420     PostString("Mesh Reduction Algorithm (non-optimized)",1,0,5);
00421     sprintf(buf,"was executed in %5.3f seconds",DeltaT);
00422     PostString(buf,2,1,6);
00423 
00424     while (1) {
00425         while(PeekMessage(&msg, hWnd, 0, 0, PM_NOREMOVE)) {
00426             if(GetMessage(&msg, hWnd, 0, 0)) {
00427                 TranslateMessage(&msg);
00428                 DispatchMessage(&msg);
00429             } else {
00430                 goto quit; // This 'goto' was in the sample code
00431             }
00432         }
00433         CalcFPSDeltaT();
00434         Display();
00435     }
00436 
00437   quit:
00438     wglMakeCurrent(NULL, NULL);
00439     ReleaseDC(hDC, hWnd);
00440     wglDeleteContext(hRC);
00441     DestroyWindow(hWnd);
00442     if (hPalette) DeleteObject(hPalette);
00443     return msg.wParam;
00444 }
00445 
00446 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines