Initial commit for version 2.0.x patch release
[OpenFOAM-2.0.x.git] / applications / utilities / surface / surfaceCoarsen / bunnylod / winmain.C
blob721460cbf685f5cb01bef9e1326a4841bcf21b42
1 /*
2  *        Polygon Reduction Demo by Stan Melax (c) 1998
3  *  Permission to use any of this code wherever you want is granted..
4  *  Although, please do acknowledge authorship if appropriate.
5  *
6  *  This module contains the window setup code, mouse input, timing
7  *  routines, and that sort of stuff.  The interesting modules
8  *  to see are bunnygut.cpp and progmesh.cpp.
9  *
10  *  The windows 95 specific code for this application was taken from
11  *  an example of processing mouse events in an OpenGL program using
12  *  the Win32 API from the www.opengl.org web site.
13  *
14  *  Under Project->Settings, Link Options, General Category
15  *  Add:
16  *        Opengl32.lib glu32.lib winmm.lib
17  *  to the Object/Library Modules
18  *
19  *  You will need have OpenGL libs and include files to compile this
20  *  Go to the www.opengl.org web site if you need help with this.
21  */
24 #include <windows.h>    /* must include this before GL/gl.h */
25 #include <GL/gl.h>              /* OpenGL header file */
26 #include <GL/glu.h>             /* OpenGL utilities header file */
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/timeb.h>
30 #include <time.h>
32 #include "vector.h"
33 #include "font.h"
35 // Functions and Variables from bunny module
36 extern void       InitModel();
37 extern void       RenderModel();
38 extern Vector     model_position;      // position of bunny
39 extern Quaternion model_orientation;   // orientation of bunny
41 // Global Variables
42 float   DeltaT = 0.1f;
43 float   FPS;
44 int     Width  = 512;
45 int     Height = 512;
46 int     MouseX = 0;
47 int     MouseY = 0;
48 Vector  MouseVector;      // 3D direction mouse points
49 Vector  OldMouseVector;
50 int     MouseState=0;     // true iff left button down
51 float   ViewAngle=45.0f;
53 HDC hDC;                /* device context */
54 HPALETTE hPalette = 0;  /* custom palette (if needed) */
57 void CalcFPSDeltaT(){
58         static int timeinit=0;
59         static int start,start2,current,last;
60         static int frame=0, frame2=0;
61         if(!timeinit){
62                 frame=0;
63                 start=timeGetTime();
64                 timeinit=1;
65         }
66         frame++;
67         frame2++;
68         current=timeGetTime(); // found in winmm.lib
69         double dif=(double)(current-start)/CLOCKS_PER_SEC;
70         double rv = (dif)? (double)frame/(double)dif:-1.0;
71         if(dif>2.0 && frame >10) {
72                 start  = start2;
73                 frame  = frame2;
74                 start2 = timeGetTime();
75                 frame2 = 0;
76         }
77         DeltaT = (float)(current-last)/CLOCKS_PER_SEC;
78         if(current==last) {
79                 DeltaT = 0.1f/CLOCKS_PER_SEC;  // it just cant be 0
80         }
81         // if(DeltaT>1.0) DeltaT=1.0;
82         FPS = (float)rv;
83         last = current;
87 void ComputeMouseVector(){
88         OldMouseVector=MouseVector;
89         float spread = (float)tan(ViewAngle/2*3.14/180);
90         float y = spread * ((Height-MouseY)-Height/2.0f) /(Height/2.0f);
91     float x = spread * (MouseX-Width/2.0f)  /(Height/2.0f);
92     Vector v(x ,y,-1);
93     // v=UserOrientation *v;
94     v=normalize(v);
95         MouseVector = v;
98 Quaternion VirtualTrackBall(Vector cop,Vector cor,Vector dir1,Vector dir2) {
99         // Implement track ball functionality to spin stuf on the screen
100         //  cop   center of projection
101         //  cor   center of rotation
102         //  dir1  old mouse direction
103         //  dir2  new mouse direction
104         // pretend there is a sphere around cor.  Then find the points
105         // where dir1 and dir2 intersect that sphere.  Find the
106         // rotation that takes the first point to the second.
107         float m;
108         // compute plane
109         Vector nrml = cor - cop;
110          // since trackball proportional to distance from cop
111         float fudgefactor = 1.0f/(magnitude(nrml) * 0.25f);
112         nrml = normalize(nrml);
113         float dist = -(nrml^cor);
114         Vector u= planelineintersection(nrml,dist,cop,cop+dir1);
115         u=u-cor;
116         u=u*fudgefactor;
117         m= magnitude(u);
118         if(m>1) {u=u*1.0f/m;}
119         else {
120                 u=u - (nrml * (float)sqrt(1-m*m));
121         }
122         Vector v= planelineintersection(nrml,dist,cop,cop+dir2);
123         v=v-cor;
124         v=v*fudgefactor;
125         m= magnitude(v);
126         if(m>1) {v=v*1.0f/m;}
127         else {
128                 v=v - (nrml * (float)sqrt(1-m*m));
129         }
130         Vector axis = u*v;
131         float angle;
132         m=magnitude(axis);
133         if(m>1)m=1; // avoid potential floating point error
134         Quaternion q(Vector(1.0f,0.0f,0.0f),0.0f);
135         if(m>0 && (angle=(float)asin(m))>3.14/180) {
136                         axis = normalize(axis);
137                         q=Quaternion(axis,angle);
138         }
139         return q;
142 void SpinIt(){
143         // Change the orientation of the bunny according to mouse drag
144         Quaternion q=VirtualTrackBall(Vector(0,0,0),model_position,
145                                       OldMouseVector,MouseVector);
146         model_orientation=q*model_orientation;
149 void Reshape(int width, int height){
150         // called initially and when the window changes size
151         Width=width;
152         Height=height;
153     glViewport(0, 0, width, height);
154     glMatrixMode(GL_PROJECTION);
155     glLoadIdentity();
156     gluPerspective(ViewAngle, (float)width/height, 0.1, 50.0);
157     glMatrixMode(GL_MODELVIEW);
158     glLoadIdentity();
161 void PrintStats(){
162         char buf[1024];buf[0]='\0';
163         sprintf(buf,"FPS: %5.2f   ",FPS);
164         PostString(buf,0,-1,0);
167 void Display(){
168         // main drawing routine - called every frame
169     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
170     glPushMatrix();
171         glLoadIdentity();
172         // camera at default (zero) position and orientation
173         RenderModel();
174         PrintStats();
175         glLoadIdentity();
176         RenderStrings();
177     glPopMatrix();
178     glFlush();
179     SwapBuffers(hDC);                   /* nop if singlebuffered */
183 LONG WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
185     static PAINTSTRUCT ps;
186     static GLboolean left  = GL_FALSE;  /* left button currently down? */
187     static GLboolean right = GL_FALSE;  /* right button currently down? */
188     static int omx, omy, mx, my;
190     switch(uMsg) {
191     case WM_PAINT:
192                 BeginPaint(hWnd, &ps);
193                 EndPaint(hWnd, &ps);
194                 return 0;
195     case WM_SIZE:
196                 Reshape(LOWORD(lParam), HIWORD(lParam));
197                 PostMessage(hWnd, WM_PAINT, 0, 0);
198                 return 0;
199     case WM_CHAR:
200                 switch (wParam) {
201                         case 27: /* ESC key */
202                             PostQuitMessage(0);
203                             break;
204                 }
205                 return 0;
207         case WM_LBUTTONDOWN:
208             /* if we don't set the capture we won't get mouse move
209            messages when the mouse moves outside the window. */
210                 SetCapture(hWnd);
211                 MouseX = LOWORD(lParam);
212                 MouseY = HIWORD(lParam);
213                 ComputeMouseVector();
214                 MouseState = 1;
215                 return 0;
217     case WM_LBUTTONUP:
218                 MouseX = LOWORD(lParam);
219                 MouseY = HIWORD(lParam);
220             if(MouseX & 1 << 15) MouseX -= (1 << 16);
221             if(MouseY & 1 << 15) MouseY -= (1 << 16);
222                 ComputeMouseVector();
223                 if(MouseState) SpinIt();
224                 MouseState=0;
225                 /* remember to release the capture when we are finished. */
226                 ReleaseCapture();
227                 return 0;
229     case WM_MOUSEMOVE:
230                 MouseX = LOWORD(lParam);
231                 MouseY = HIWORD(lParam);
232             /* Win32 is pretty braindead about the x, y position that
233                it returns when the mouse is off the left or top edge
234                of the window (due to them being unsigned). therefore,
235                roll the Win32's 0..2^16 pointer co-ord range to the
236                more amenable (and useful) 0..+/-2^15. */
237             if(MouseX & 1 << 15) MouseX -= (1 << 16);
238             if(MouseY & 1 << 15) MouseY -= (1 << 16);
239                 ComputeMouseVector();
240                 if(MouseState) SpinIt();
241                 return 0;
243     case WM_PALETTECHANGED:
244                 if (hWnd == (HWND)wParam) break;
245                 /* fall through to WM_QUERYNEWPALETTE */
246     case WM_QUERYNEWPALETTE:
247                 if (hPalette) {
248                     UnrealizeObject(hPalette);
249                     SelectPalette(hDC, hPalette, FALSE);
250                     RealizePalette(hDC);
251                     return TRUE;
252                 }
253                 return FALSE;
255     case WM_CLOSE:
256                 PostQuitMessage(0);
257                 return 0;
258     }
259     return DefWindowProc(hWnd, uMsg, wParam, lParam);
262 HWND CreateOpenGLWindow(char* title)
264         // make a double-buffered, rgba, opengl window
265     int         n, pf;
266     HWND        hWnd;
267     WNDCLASS    wc;
268     LOGPALETTE* lpPal;
269     PIXELFORMATDESCRIPTOR pfd;
270     static HINSTANCE hInstance = 0;
272     /* only register the window class once - use hInstance as a flag. */
273     if (!hInstance) {
274                 hInstance = GetModuleHandle(NULL);
275                 wc.style         = CS_OWNDC;
276                 wc.lpfnWndProc   = (WNDPROC)WindowProc;
277                 wc.cbClsExtra    = 0;
278                 wc.cbWndExtra    = 0;
279                 wc.hInstance     = hInstance;
280                 wc.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
281                 wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
282                 wc.hbrBackground = NULL;
283                 wc.lpszMenuName  = NULL;
284                 wc.lpszClassName = "OpenGL";
286                 if (!RegisterClass(&wc)) {
287                         MessageBox(NULL, "RegisterClass() failed:  "
288                                    "Cannot register window class.",
289                                    "Error", MB_OK);
290                         return NULL;
291                 }
292     }
294     hWnd = CreateWindow("OpenGL", title, WS_OVERLAPPEDWINDOW |
295                         WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
296                         0,0,Width,Height, NULL, NULL, hInstance, NULL);
298     if (hWnd == NULL) {
299                 MessageBox(NULL,
300                            "CreateWindow() failed:  Cannot create a window.",
301                            "Error", MB_OK);
302                 return NULL;
303     }
305     hDC = GetDC(hWnd);
307     /* there is no guarantee that the contents of the stack that become
308        the pfd are zeroed, therefore _make sure_ to clear these bits. */
309     memset(&pfd, 0, sizeof(pfd));
310     pfd.nSize        = sizeof(pfd);
311     pfd.nVersion     = 1;
312     pfd.dwFlags      = PFD_DRAW_TO_WINDOW
313                      | PFD_SUPPORT_OPENGL
314                      | PFD_DOUBLEBUFFER;
315     pfd.iPixelType   = PFD_TYPE_RGBA;
316     pfd.cDepthBits   = 32;
317     pfd.cColorBits   = 32;
319     pf = ChoosePixelFormat(hDC, &pfd);
320     if (pf == 0) {
321                 MessageBox(NULL, "ChoosePixelFormat() failed:  "
322                            "Cannot find a suitable pixel format.",
323                            "Error", MB_OK);
324                 return 0;
325     }
327     if (SetPixelFormat(hDC, pf, &pfd) == FALSE) {
328                 MessageBox(NULL, "SetPixelFormat() failed:  "
329                            "Cannot set format specified.", "Error", MB_OK);
330                 return 0;
331     }
333     DescribePixelFormat(hDC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
335     if (pfd.dwFlags & PFD_NEED_PALETTE ||
336                 pfd.iPixelType == PFD_TYPE_COLORINDEX) {
338                 n = 1 << pfd.cColorBits;
339                 if (n > 256) n = 256;
341                 lpPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +
342                                                 sizeof(PALETTEENTRY) * n);
343                 memset(lpPal, 0, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * n);
344                 lpPal->palVersion = 0x300;
345                 lpPal->palNumEntries = n;
347                 GetSystemPaletteEntries(hDC, 0, n, &lpPal->palPalEntry[0]);
349                 /* if the pixel type is RGBA, then we want to make an RGB ramp,
350                    otherwise (color index) set individual colors. */
351                 if (pfd.iPixelType == PFD_TYPE_RGBA) {
352                         int redMask = (1 << pfd.cRedBits) - 1;
353                         int greenMask = (1 << pfd.cGreenBits) - 1;
354                         int blueMask = (1 << pfd.cBlueBits) - 1;
355                         int i;
357                         /* fill in the entries with an RGB color ramp. */
358                         for (i = 0; i < n; ++i) {
359                         lpPal->palPalEntry[i].peRed =
360                                 (((i >> pfd.cRedShift)   & redMask)   * 255)
361                                /redMask;
362                         lpPal->palPalEntry[i].peGreen =
363                                 (((i >> pfd.cGreenShift) & greenMask) * 255)
364                                /greenMask;
365                         lpPal->palPalEntry[i].peBlue =
366                                 (((i >> pfd.cBlueShift)  & blueMask)  * 255)
367                                /blueMask;
368                         lpPal->palPalEntry[i].peFlags = 0;
369                         }
370                 } else {
371                         lpPal->palPalEntry[0].peRed = 0;
372                         lpPal->palPalEntry[0].peGreen = 0;
373                         lpPal->palPalEntry[0].peBlue = 0;
374                         lpPal->palPalEntry[0].peFlags = PC_NOCOLLAPSE;
375                         lpPal->palPalEntry[1].peRed = 255;
376                         lpPal->palPalEntry[1].peGreen = 0;
377                         lpPal->palPalEntry[1].peBlue = 0;
378                         lpPal->palPalEntry[1].peFlags = PC_NOCOLLAPSE;
379                         lpPal->palPalEntry[2].peRed = 0;
380                         lpPal->palPalEntry[2].peGreen = 255;
381                         lpPal->palPalEntry[2].peBlue = 0;
382                         lpPal->palPalEntry[2].peFlags = PC_NOCOLLAPSE;
383                         lpPal->palPalEntry[3].peRed = 0;
384                         lpPal->palPalEntry[3].peGreen = 0;
385                         lpPal->palPalEntry[3].peBlue = 255;
386                         lpPal->palPalEntry[3].peFlags = PC_NOCOLLAPSE;
387                 }
389                 hPalette = CreatePalette(lpPal);
390                 if (hPalette) {
391                         SelectPalette(hDC, hPalette, FALSE);
392                         RealizePalette(hDC);
393                 }
395                 free(lpPal);
396     }
398     ReleaseDC(hDC, hWnd);
399     return hWnd;
402 int APIENTRY WinMain(HINSTANCE hCurrentInst, HINSTANCE hPreviousInst,
403         LPSTR lpszCmdLine, int nCmdShow)
405     HGLRC hRC;                          /* opengl context */
406     HWND  hWnd;                         /* window */
407     MSG   msg;                          /* message */
409         // InitModel() initializes some data structures and
410         // does the progressive mesh polygon reduction algorithm
411         // on the model.
412         CalcFPSDeltaT(); // to time the algorithm
413         InitModel();
414         CalcFPSDeltaT();
416         hWnd = CreateOpenGLWindow("bunnylod by Stan Melax");
417     if (hWnd == NULL) exit(1);
419     hDC = GetDC(hWnd);
420     hRC = wglCreateContext(hDC);
421     wglMakeCurrent(hDC, hRC);
422     ShowWindow(hWnd, nCmdShow);
423         glEnable(GL_DEPTH_TEST);
425         PostString("Demo by Stan Melax (c)1998",5,-5,20);
426         PostString("Model by Viewpoint Datalabs (c)1996",5,-4,20);
427         char buf[128];
428         PostString("Mesh Reduction Algorithm (non-optimized)",1,0,5);
429         sprintf(buf,"was executed in %5.3f seconds",DeltaT);
430         PostString(buf,2,1,6);
432     while (1) {
433                 while(PeekMessage(&msg, hWnd, 0, 0, PM_NOREMOVE)) {
434                     if(GetMessage(&msg, hWnd, 0, 0)) {
435                                 TranslateMessage(&msg);
436                                 DispatchMessage(&msg);
437                     } else {
438                                 // This 'goto' was in the sample code
439                                 goto quit;
440                     }
441                 }
442                 CalcFPSDeltaT();
443                 Display();
444     }
446   quit:
447     wglMakeCurrent(NULL, NULL);
448     ReleaseDC(hDC, hWnd);
449     wglDeleteContext(hRC);
450     DestroyWindow(hWnd);
451     if (hPalette) DeleteObject(hPalette);
452     return msg.wParam;