00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <windows.h>
00026 #include <GL/gl.h>
00027 #include <GL/glu.h>
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
00037 extern void InitModel();
00038 extern void RenderModel();
00039 extern Vector model_position;
00040 extern Quaternion model_orientation;
00041
00042
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;
00050 Vector OldMouseVector;
00051 int MouseState=0;
00052 float ViewAngle=45.0f;
00053
00054 HDC hDC;
00055 HPALETTE hPalette = 0;
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();
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;
00081 }
00082
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
00095 v=normalize(v);
00096 MouseVector = v;
00097 }
00098
00099 Quaternion VirtualTrackBall(Vector cop,Vector cor,Vector dir1,Vector dir2) {
00100
00101
00102
00103
00104
00105
00106
00107
00108 float m;
00109
00110 Vector nrml = cor - cop;
00111 float fudgefactor = 1.0f/(magnitude(nrml) * 0.25f);
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;
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
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
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
00169 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00170 glPushMatrix();
00171 glLoadIdentity();
00172
00173 RenderModel();
00174 PrintStats();
00175 glLoadIdentity();
00176 RenderStrings();
00177 glPopMatrix();
00178 glFlush();
00179 SwapBuffers(hDC);
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;
00187 static GLboolean right = GL_FALSE;
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:
00202 PostQuitMessage(0);
00203 break;
00204 }
00205 return 0;
00206
00207 case WM_LBUTTONDOWN:
00208
00209
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
00226 ReleaseCapture();
00227 return 0;
00228
00229 case WM_MOUSEMOVE:
00230 MouseX = LOWORD(lParam);
00231 MouseY = HIWORD(lParam);
00232
00233
00234
00235
00236
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
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
00265 int n, pf;
00266 HWND hWnd;
00267 WNDCLASS wc;
00268 LOGPALETTE* lpPal;
00269 PIXELFORMATDESCRIPTOR pfd;
00270 static HINSTANCE hInstance = 0;
00271
00272
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
00306
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
00345
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
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;
00398 HWND hWnd;
00399 MSG msg;
00400
00401
00402
00403
00404 CalcFPSDeltaT();
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;
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