glapp.cpp
上传用户:qccn516
上传日期:2013-05-02
资源大小:3382k
文件大小:20k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /* OpenGL App
  2.  *
  3.  * Copyright (C) 2003-2004, Alexander Zaprjagaev <frustum@frustum.org>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19. #ifndef _WIN32
  20. /* linux
  21.  */
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <stdarg.h>
  26. #include <sys/time.h>
  27. #include <X11/Xlib.h>
  28. #include <X11/keysym.h>
  29. #include <X11/extensions/xf86vmode.h>
  30. #include <GL/gl.h>
  31. #include <GL/glu.h>
  32. #include <GL/glx.h>
  33. #ifdef HAVE_GTK
  34. #include <gtk/gtk.h>
  35. #include <gdk/gdkx.h>
  36. #endif
  37. #include "glapp.h"
  38. static Display *display;
  39. static int screen;
  40. static XF86VidModeModeInfo **modes;
  41. static Window window;
  42. static GLXContext context;
  43. static Atom WM_DELETE_WINDOW;
  44. static Cursor cursor;
  45. static int done;
  46. /*
  47.  */
  48. GLApp::GLApp() {
  49. memset(this,0,sizeof(GLApp));
  50. #ifdef HAVE_GTK
  51. gtk_init(NULL,NULL);
  52. display = GDK_DISPLAY();
  53. #else
  54. display = XOpenDisplay(NULL);
  55. if(!display) exit("couldn`t open display");
  56. #endif
  57. }
  58. GLApp::~GLApp() {
  59. if(context) glXDestroyContext(display,context);
  60. if(window) XDestroyWindow(display,window);
  61. if(modes) XF86VidModeSwitchToMode(display,screen,modes[0]);
  62. if(display) XCloseDisplay(display);
  63. }
  64. /*
  65.  */
  66. static int modescmp(const void *pa,const void *pb) {
  67. XF86VidModeModeInfo *a = *(XF86VidModeModeInfo**)pa;
  68. XF86VidModeModeInfo *b = *(XF86VidModeModeInfo**)pb;
  69. if(a->hdisplay > b->hdisplay) return -1;
  70. return b->vdisplay - a->vdisplay;
  71. }
  72. /*
  73.  */
  74. int GLApp::setVideoMode(int w,int h,int fs) {
  75. if(window) {
  76. XDestroyWindow(display,window);
  77. if(modes) XF86VidModeSwitchToMode(display,screen,modes[0]);
  78. }
  79. windowWidth = w;
  80. windowHeight = h;
  81. fullScreen = fs;
  82. try {
  83. int attrib[] = {
  84. GLX_RGBA,
  85. GLX_RED_SIZE,8,
  86. GLX_GREEN_SIZE,8,
  87. GLX_BLUE_SIZE,8,
  88. GLX_ALPHA_SIZE,8,
  89. GLX_DEPTH_SIZE,24,
  90. GLX_STENCIL_SIZE,8,
  91. GLX_DOUBLEBUFFER,
  92. None
  93. };
  94. screen = DefaultScreen(display);
  95. Window rootWindow = RootWindow(display,screen);
  96. XVisualInfo *visual = glXChooseVisual(display,screen,attrib);
  97. if(!visual) throw("couldn`t get an RGBA, double-buffered visual");
  98. if(fullScreen) {
  99. int i,nmodes;
  100. XF86VidModeModeLine mode;
  101. if(XF86VidModeGetModeLine(display,screen,&nmodes,&mode) && XF86VidModeGetAllModeLines(display,screen,&nmodes,&modes)) {
  102. qsort(modes,nmodes,sizeof(XF86VidModeModeInfo*),modescmp);
  103. for(i = nmodes - 1; i > 0; i--) if (modes[i]->hdisplay >= windowWidth && modes[i]->vdisplay >= windowHeight) break;
  104. if(modes[i]->hdisplay != mode.hdisplay || modes[i]->vdisplay != mode.vdisplay) {
  105. windowWidth = modes[i]->hdisplay;
  106. windowHeight = modes[i]->vdisplay;
  107. XF86VidModeSwitchToMode(display,screen,modes[i]);
  108. }
  109. XF86VidModeSetViewPort(display,screen,0,0);
  110. } else fullScreen = 0;
  111. }
  112. XSetWindowAttributes attr;
  113. unsigned long mask;
  114. attr.background_pixel = 0;
  115. attr.border_pixel = 0;
  116. attr.colormap = XCreateColormap(display,rootWindow,visual->visual,AllocNone);
  117. attr.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask;
  118. if(fullScreen) {
  119. mask = CWBackPixel | CWColormap | CWOverrideRedirect | CWSaveUnder | CWBackingStore | CWEventMask;
  120. attr.override_redirect = True;
  121. attr.backing_store = NotUseful;
  122. attr.save_under = False;
  123. } else {
  124. mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
  125. }
  126. window = XCreateWindow(display,rootWindow,0,0,windowWidth,windowHeight,0,visual->depth,InputOutput,visual->visual,mask,&attr);
  127. XMapWindow(display,window);
  128. if(fullScreen) {
  129. XMoveWindow(display,window,0,0);
  130. XRaiseWindow(display,window);
  131. XWarpPointer(display,None,window,0,0,0,0,windowWidth / 2,windowHeight / 2);
  132. XFlush(display);
  133. XF86VidModeSetViewPort(display,screen,0,0);
  134. XGrabPointer(display,window,True,0,GrabModeAsync,GrabModeAsync,window,None,CurrentTime);
  135. XGrabKeyboard(display,window,True,GrabModeAsync,GrabModeAsync,CurrentTime);
  136. } else {
  137. WM_DELETE_WINDOW = XInternAtom(display,"WM_DELETE_WINDOW",False);
  138. XSetWMProtocols(display,window,&WM_DELETE_WINDOW,1);
  139. }
  140. XFlush(display);
  141. if(!context) context = glXCreateContext(display,visual,NULL,True);
  142. if(!context) throw("glXCreateContext failed");
  143. glXMakeCurrent(display,window,context);
  144. glViewport(0,0,windowWidth,windowHeight);
  145. }
  146. catch(const char *error) {
  147. window = 0;
  148. exit(error);
  149. return 0;
  150. }
  151. return 1;
  152. }
  153. /*
  154.  */
  155. void GLApp::setTitle(const char *title) {
  156. strcpy(this->title,title);
  157. XStoreName(display,window,title);
  158. XSetIconName(display,window,title);
  159. }
  160. /*
  161.  */
  162. void GLApp::setCursor(int x,int y) {
  163. XWarpPointer(display,None,window,0,0,0,0,x,y);
  164. XFlush(display);
  165. }
  166. /*
  167.  */
  168. void GLApp::showCursor(int show) {
  169. if(show) XDefineCursor(display,window,0);
  170. else {
  171. if(!cursor) {
  172. char data[] = { 0 };
  173. Pixmap blank;
  174. XColor dummy;
  175. blank = XCreateBitmapFromData(display,window,data,1,1);
  176. cursor = XCreatePixmapCursor(display,blank,blank,&dummy,&dummy,0,0);
  177. XFreePixmap(display,blank);
  178. }
  179. XDefineCursor(display,window,cursor);
  180. }
  181. }
  182. /*
  183.  */
  184. void GLApp::checkExtension(const char *extension) {
  185. static char *extensions = NULL;
  186. if(!extensions) extensions = (char*)glGetString(GL_EXTENSIONS);
  187. if(strstr(extensions,extension)) return;
  188. char error[1024];
  189. sprintf(error,"OpenGL extension "%s" is not supported by current hardware",extension);
  190. exit(error);
  191. }
  192. /*
  193.  */
  194. void GLApp::error() {
  195. GLenum error;
  196. while((error = glGetError()) != GL_NO_ERROR) {
  197. #ifdef HAVE_GTK_2
  198. GtkWidget *dialog = gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,"OpenGL error 0x%04X: %sn",error,gluErrorString(error));
  199. gtk_dialog_run(GTK_DIALOG(dialog));
  200. gtk_widget_destroy(dialog);
  201. #else
  202. fprintf(stderr,"OpenGL error 0x%04X: %sn",error,gluErrorString(error));
  203. #endif
  204. }
  205. }
  206. /*
  207.  */
  208. void GLApp::exit(const char *error,...) {
  209. if(error) {
  210. char buf[1024];
  211. va_list arg;
  212. va_start(arg,error);
  213. vsprintf(buf,error,arg);
  214. va_end(arg);
  215. #ifdef HAVE_GTK_2
  216. GtkWidget *dialog = gtk_message_dialog_new(NULL,GTK_DIALOG_MODAL,GTK_MESSAGE_ERROR,GTK_BUTTONS_OK,"GLApp exit: %sn",buf);
  217. gtk_dialog_run(GTK_DIALOG(dialog));
  218. gtk_widget_destroy(dialog);
  219. #else
  220. fprintf(stderr,"GLApp exit: %sn",buf);
  221. #endif
  222. }
  223. done = 1;
  224. }
  225. /*
  226.  */
  227. #ifdef HAVE_GTK
  228. static int ret;
  229. static char *name;
  230. static void signal_ok(GtkWidget *widget) {
  231. ret = 1;
  232. strcpy(name,gtk_file_selection_get_filename(GTK_FILE_SELECTION(widget)));
  233. gtk_widget_destroy(widget);
  234. gtk_main_quit();
  235. }
  236. static void signal_cancel(GtkWidget *widget) {
  237. gtk_widget_destroy(widget);
  238. gtk_main_quit();
  239. }
  240. int GLApp::selectFile(const char *title,char *name) {
  241. ret = 0;
  242. ::name = name;
  243. GtkWidget *window = gtk_file_selection_new(title);
  244. gtk_window_set_position(GTK_WINDOW(window),GTK_WIN_POS_CENTER);
  245. gtk_signal_connect(GTK_OBJECT(window),"destroy",GTK_SIGNAL_FUNC(signal_cancel),&window);
  246. gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(window)->ok_button),"clicked",GTK_SIGNAL_FUNC(signal_ok),GTK_OBJECT(window));
  247. gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(window)->cancel_button),"clicked",GTK_SIGNAL_FUNC(signal_cancel),GTK_OBJECT(window));
  248. gtk_widget_show(window);
  249. gtk_main();
  250. return ret;
  251. }
  252. #else
  253. int GLApp::selectFile(const char *title,char *name) {
  254. printf("%sn",title);
  255. fscanf(stdin,"%s",name);
  256. return 1;
  257. }
  258. #endif /* HAVE_GTK */
  259. /*
  260.  */
  261. static int getTime() {
  262. struct timeval tval;
  263. struct timezone tzone;
  264. gettimeofday(&tval,&tzone);
  265. return tval.tv_sec * 1000 + tval.tv_usec / 1000;
  266. }
  267. /*
  268.  */
  269. static int translateKey(int key) {
  270. int ret;
  271. if(key & 0xff00) {
  272. switch(key) {
  273. case XK_Escape: ret = GLApp::KEY_ESC; break;
  274. case XK_Tab: ret = GLApp::KEY_TAB; break;
  275. case XK_Return: ret = GLApp::KEY_RETURN; break;
  276. case XK_BackSpace: ret = GLApp::KEY_BACKSPACE; break;
  277. case XK_Delete: ret = GLApp::KEY_DELETE; break;
  278. case XK_Home: ret = GLApp::KEY_HOME; break;
  279. case XK_End: ret = GLApp::KEY_END; break;
  280. case XK_Page_Up: ret = GLApp::KEY_PGUP; break;
  281. case XK_Page_Down: ret = GLApp::KEY_PGDOWN; break;
  282. case XK_Left: ret = GLApp::KEY_LEFT; break;
  283. case XK_Right: ret = GLApp::KEY_RIGHT; break;
  284. case XK_Up: ret = GLApp::KEY_UP; break;
  285. case XK_Down: ret = GLApp::KEY_DOWN; break;
  286. case XK_Shift_L: case XK_Shift_R: ret = GLApp::KEY_SHIFT; break;
  287. case XK_Control_L: case XK_Control_R: ret = GLApp::KEY_CTRL; break;
  288. case XK_Alt_L: case XK_Alt_R: ret = GLApp::KEY_ALT; break;
  289. default: ret = (key < 0x06ff) ? (key & 0x00ff) : 0;
  290. }
  291. } else {
  292. ret = key;
  293. }
  294. return ret;
  295. }
  296. /*
  297.  */
  298. void GLApp::main() {
  299. KeySym key;
  300. int startTime = getTime(),endTime = 0,counter = 0;
  301.     fps = 60;
  302. while(window && !done) {
  303. while(XPending(display) > 0) {
  304. XEvent event;
  305. XNextEvent(display,&event);
  306. switch(event.type) {
  307. case ClientMessage:
  308. if(event.xclient.format == 32 && event.xclient.data.l[0] == (long)WM_DELETE_WINDOW) exit();
  309. break;
  310. case ConfigureNotify:
  311. windowWidth = event.xconfigure.width;
  312. windowHeight = event.xconfigure.height;
  313. glViewport(0,0,windowWidth,windowHeight);
  314. break;
  315. case KeyPress:
  316. XLookupString(&event.xkey,NULL,0,&key,NULL);
  317. key = translateKey(key);
  318. keys[key] = 1;
  319. if(keys[KEY_ALT] && keys[KEY_RETURN]) {
  320. keys[KEY_ALT] = 0;
  321. keys[KEY_RETURN] = 0;
  322. setVideoMode(windowWidth,windowHeight,!fullScreen);
  323. setTitle(title);
  324. }
  325. if(key) keyPress(key);
  326. break;
  327. case KeyRelease:
  328. XLookupString(&event.xkey,NULL,0,&key,NULL);
  329. key = translateKey(key);
  330. keys[key] = 0;
  331. if(key) keyRelease(key);
  332. break;
  333. case MotionNotify:
  334. mouseX = event.xmotion.x;
  335. mouseY = event.xmotion.y;
  336. break;
  337. case ButtonPress:
  338. mouseButton |= 1 << ((event.xbutton.button - 1));
  339. buttonPress(1 << (event.xbutton.button - 1));
  340. break;
  341. case ButtonRelease:
  342. if(event.xbutton.button < 4) mouseButton &= ~(1 << (event.xbutton.button - 1));
  343. buttonRelease(1 << (event.xbutton.button - 1));
  344. break;
  345. }
  346. }
  347. if(counter++ == 10) {
  348. endTime = startTime;
  349. startTime = getTime(); 
  350. fps = counter * 1000.0 / (float)(startTime - endTime);
  351. counter = 0;
  352. }
  353. ifps = 1.0 / fps;
  354. idle();
  355. render();
  356. glXSwapBuffers(display,window);
  357. mouseButton &= ~(BUTTON_UP | BUTTON_DOWN);
  358. }
  359. }
  360. #else
  361. /* windows
  362.  */
  363. #include <stdio.h>
  364. #include <string.h>
  365. #include <stdlib.h>
  366. #include <stdarg.h>
  367. #include <windows.h>
  368. #include <GL/gl.h>
  369. #include <GL/glu.h>
  370. #include "glapp.h"
  371. #pragma comment (lib,"opengl32.lib")
  372. #pragma comment (lib,"glu32.lib")
  373. #pragma comment (lib,"winmm.lib")
  374. extern int main(int argc,char **argv);
  375. static GLApp *glApp;
  376. static HWND window;
  377. static HGLRC context;
  378. static HCURSOR cursor;
  379. static int done;
  380. /*
  381.  */
  382. GLApp::GLApp() {
  383. memset(this,0,sizeof(GLApp));
  384. }
  385. GLApp::~GLApp() {
  386. if(window) {
  387. HDC hdc = GetDC(window);
  388. wglMakeCurrent(hdc,0);
  389. wglDeleteContext(context);
  390. ReleaseDC(window,hdc);
  391. DestroyWindow(window);
  392. if(fullScreen) {
  393. ChangeDisplaySettings(NULL,0);
  394. ShowCursor(true);
  395. }
  396. }
  397. }
  398. /*
  399.  */
  400. static int translateKey(int key) {
  401. int ret;
  402. switch(key) {
  403. case VK_ESCAPE : ret = GLApp::KEY_ESC; break;
  404. case VK_TAB: ret = GLApp::KEY_TAB; break;
  405. case VK_RETURN: ret = GLApp::KEY_RETURN; break;
  406. case VK_BACK: ret = GLApp::KEY_BACKSPACE; break;
  407. case VK_DELETE: ret = GLApp::KEY_DELETE; break;
  408. case VK_HOME: ret = GLApp::KEY_HOME; break;
  409. case VK_END: ret = GLApp::KEY_END; break;
  410. case VK_PRIOR: ret = GLApp::KEY_PGUP; break;
  411. case VK_NEXT: ret = GLApp::KEY_PGDOWN; break;
  412. case VK_LEFT: ret = GLApp::KEY_LEFT; break;
  413. case VK_RIGHT: ret = GLApp::KEY_RIGHT; break;
  414. case VK_UP: ret = GLApp::KEY_UP; break;
  415. case VK_DOWN: ret = GLApp::KEY_DOWN; break;
  416. case VK_SHIFT: ret = GLApp::KEY_SHIFT; break;
  417. case VK_CONTROL: ret = GLApp::KEY_CTRL; break;
  418. default:
  419. ret = MapVirtualKey(key,2);
  420. if(strchr("1234567890-=",ret)) {
  421. if(glApp->keys[GLApp::KEY_SHIFT]) {
  422. if(ret == '1') ret = '!';
  423. else if(ret == '2') ret = '@';
  424. else if(ret == '3') ret = '#';
  425. else if(ret == '4') ret = '$';
  426. else if(ret == '5') ret = '%';
  427. else if(ret == '6') ret = '^';
  428. else if(ret == '7') ret = '&';
  429. else if(ret == '8') ret = '*';
  430. else if(ret == '9') ret = '(';
  431. else if(ret == '0') ret = ')';
  432. else if(ret == '-') ret = '_';
  433. else if(ret == '=') ret = '+';
  434. }
  435. } else if(isascii(ret)) {
  436. if(glApp->keys[GLApp::KEY_SHIFT]) ret = toupper(ret);
  437. else ret = tolower(ret);
  438. }
  439. else ret = 0;
  440. }
  441. return ret;
  442. }
  443. /*
  444.  */
  445. LRESULT CALLBACK windowProc(HWND window,UINT message,WPARAM wparam,LPARAM lparam) {
  446. switch(message) {
  447. case WM_SIZE:
  448. glApp->windowWidth = LOWORD(lparam);
  449. glApp->windowHeight = HIWORD(lparam);
  450. glViewport(0,0,glApp->windowWidth,glApp->windowHeight);
  451. break;
  452. case WM_KEYDOWN: {
  453. int key = translateKey((int)wparam);
  454. glApp->keys[key] = 1;
  455. glApp->keyPress(key);
  456. }
  457. break;
  458. case WM_KEYUP: {
  459. int key = translateKey((int)wparam);
  460. glApp->keys[key] = 0;
  461. glApp->keyRelease(key);
  462. }
  463. break;
  464. case WM_CLOSE:
  465. glApp->exit();
  466. break;
  467. case WM_LBUTTONDOWN:
  468. glApp->mouseButton |= GLApp::BUTTON_LEFT;
  469. glApp->buttonPress(GLApp::BUTTON_LEFT);
  470. break;
  471. case WM_LBUTTONUP:
  472. glApp->mouseButton &= ~GLApp::BUTTON_LEFT;
  473. glApp->buttonRelease(GLApp::BUTTON_LEFT);
  474. break;
  475. case WM_MBUTTONDOWN:
  476. glApp->mouseButton |= GLApp::BUTTON_MIDDLE;
  477. glApp->buttonPress(GLApp::BUTTON_MIDDLE);
  478. break;
  479. case WM_MBUTTONUP:
  480. glApp->mouseButton &= ~GLApp::BUTTON_MIDDLE;
  481. glApp->buttonRelease(GLApp::BUTTON_MIDDLE);
  482. break;
  483. case WM_RBUTTONDOWN:
  484. glApp->mouseButton |= GLApp::BUTTON_RIGHT;
  485. glApp->buttonPress(GLApp::BUTTON_RIGHT);
  486. break;
  487. case WM_RBUTTONUP:
  488. glApp->mouseButton &= ~GLApp::BUTTON_RIGHT;
  489. glApp->buttonRelease(GLApp::BUTTON_RIGHT);
  490. break;
  491. case 0x020A: //WM_MOUSEWHEEL:
  492. if((short)HIWORD(wparam) > 0) {
  493. glApp->mouseButton |= GLApp::BUTTON_UP;
  494. glApp->buttonPress(GLApp::BUTTON_UP);
  495. glApp->buttonRelease(GLApp::BUTTON_UP);
  496. } else {
  497. glApp->mouseButton |= GLApp::BUTTON_DOWN;
  498. glApp->buttonPress(GLApp::BUTTON_DOWN);
  499. glApp->buttonRelease(GLApp::BUTTON_DOWN);
  500. }
  501. break;
  502. case WM_MOUSEMOVE:
  503. glApp->mouseX = LOWORD(lparam);
  504. glApp->mouseY = HIWORD(lparam);
  505. if(glApp->mouseX & 1 << 15) glApp->mouseX -= (1 << 16);
  506. if(glApp->mouseY & 1 << 15) glApp->mouseY -= (1 << 16);
  507. break;
  508. }
  509. return DefWindowProc(window,message,wparam,lparam);
  510. }
  511. /*
  512.  */
  513. int GLApp::setVideoMode(int w,int h,int fs) {
  514. if(window) {
  515. DestroyWindow(window);
  516. if(fullScreen) {
  517. ChangeDisplaySettings(NULL,0);
  518. ShowCursor(true);
  519. }
  520. }
  521. windowWidth = w;
  522. windowHeight = h;
  523. fullScreen = fs;
  524. glApp = this;
  525. try {
  526. HDC hdc;
  527. int pixelformat;
  528. PIXELFORMATDESCRIPTOR pfd = {
  529. sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
  530. PFD_TYPE_RGBA, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 8, 0, PFD_MAIN_PLANE, 0, 0, 0, 0
  531. };
  532. HINSTANCE hInstance = GetModuleHandle(NULL);
  533. if(!window) {
  534. WNDCLASS wc;
  535. wc.style = 0;
  536. wc.lpfnWndProc = (WNDPROC)windowProc;
  537. wc.cbClsExtra = 0;
  538. wc.cbWndExtra = 0;
  539. wc.hInstance = hInstance;
  540. wc.hIcon = 0;
  541. wc.hCursor = LoadCursor(NULL,IDC_ARROW);
  542. wc.hbrBackground = NULL;
  543. wc.lpszMenuName = NULL;
  544. wc.lpszClassName = "GLApp";
  545. if(!RegisterClass(&wc)) throw("RegisterClass() fail");
  546. }
  547. if(fullScreen) {
  548. DEVMODE settings;
  549. memset(&settings,0,sizeof(DEVMODE));
  550. settings.dmSize = sizeof(DEVMODE);
  551. settings.dmPelsWidth = w;
  552. settings.dmPelsHeight = h;
  553. settings.dmBitsPerPel = 32;
  554. settings.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
  555. if(ChangeDisplaySettings(&settings,CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) throw("ChangeDisplaySettings() fail");
  556. window = CreateWindowEx(0,"GLApp","GLApp",WS_POPUP,0,0,windowWidth,windowHeight,NULL,NULL,hInstance,NULL);
  557. } else {
  558. RECT windowRect = {0, 0, windowWidth, windowHeight };
  559. AdjustWindowRectEx(&windowRect,WS_OVERLAPPEDWINDOW,0,0);
  560. windowWidth = windowRect.right - windowRect.left;
  561. windowHeight = windowRect.bottom - windowRect.top;
  562. window = CreateWindowEx(0,"GLApp","GLApp",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,windowWidth,windowHeight,NULL,NULL,hInstance,NULL);
  563. }
  564. if(!window) throw("CreateWindowEx() fail");
  565. if(!(hdc = GetDC(window))) throw("GetDC() fail");
  566. if(!(pixelformat = ChoosePixelFormat(hdc,&pfd))) throw("ChoosePixelFormat() fail");
  567. if(!(SetPixelFormat(hdc,pixelformat,&pfd))) throw("SetPixelFormat() fail");
  568. if(!context) context = wglCreateContext(hdc);
  569. if(!context) throw("wglCreateContext() fail");
  570. if(!wglMakeCurrent(hdc,context)) throw("wglMakeCurrent() fail");
  571. glViewport(0,0,glApp->windowWidth,glApp->windowHeight);
  572. }
  573. catch(const char *error) {
  574. window = 0;
  575. exit(error);
  576. return 0;
  577. }
  578. ShowWindow(window,SW_SHOW);
  579. UpdateWindow(window);
  580. SetForegroundWindow(window);
  581. SetFocus(window);
  582. return 1;
  583. }
  584. /*
  585.  */
  586. void GLApp::setTitle(const char *title) {
  587. SetWindowText(window,title);
  588. }
  589. /*
  590.  */
  591. void GLApp::setCursor(int x,int y) {
  592. POINT pt;
  593. pt.x = x;
  594. pt.y = y;
  595. ClientToScreen(window,&pt);
  596. SetCursorPos(pt.x,pt.y);
  597. }
  598. /*
  599.  */
  600. void GLApp::showCursor(int show) {
  601. if(!cursor) cursor = GetCursor();
  602. if(show) SetCursor(cursor);
  603. else SetCursor(NULL);
  604. }
  605. /*
  606.  */
  607. void GLApp::checkExtension(const char *extension) {
  608. static char *extensions = NULL;
  609. if(!extensions) extensions = (char*)glGetString(GL_EXTENSIONS);
  610. if(strstr(extensions,extension)) return;
  611. char error[1024];
  612. sprintf(error,"OpenGL extension "%s" is not supported by current hardware",extension);
  613. exit(error);
  614. }
  615. /*
  616.  */
  617. void GLApp::error() {
  618. GLenum error;
  619. while((error = glGetError()) != GL_NO_ERROR) {
  620. MessageBox(0,(char*)gluErrorString(error),"OpenGL error",MB_OK);
  621. }
  622. }
  623. /*
  624.  */
  625. void GLApp::exit(const char *error,...) {
  626. if(error) {
  627. char buf[1024];
  628. va_list arg;
  629. va_start(arg,error);
  630. vsprintf(buf,error,arg);
  631. va_end(arg);
  632. MessageBox(0,buf,"GLApp exit",MB_OK);
  633. }
  634. done = 1;
  635. }
  636. /*
  637.  */
  638. int GLApp::selectFile(const char *title,char *name) {
  639. OPENFILENAME ofn;
  640. memset(&ofn,0,sizeof(ofn));
  641. ofn.lStructSize = sizeof(OPENFILENAME);
  642. ofn.hwndOwner = window;
  643. ofn.lpstrFileTitle = name;
  644. ofn.nMaxFileTitle = 512;
  645. ofn.lpstrFilter = "*.*";
  646. ofn.nFilterIndex = 1;
  647. ofn.lpstrTitle = title;
  648. ofn.Flags = OFN_FILEMUSTEXIST;
  649. return GetOpenFileName(&ofn);
  650. }
  651. /*
  652.  */
  653. static int getTime() {
  654. static int base;
  655. static int initialized = 0;
  656. if(!initialized) {
  657. base = timeGetTime();
  658. initialized = 1;
  659. }
  660. return timeGetTime() - base;
  661. }
  662. /*
  663.  */
  664. void GLApp::main() {
  665. int startTime = 0,endTime = 0,counter = 0;
  666. fps = 60;
  667. MSG msg;
  668. while(window && !done) {
  669. if(PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)) {
  670. if(!GetMessage(&msg,NULL,0,0)) return;
  671. TranslateMessage(&msg);
  672. DispatchMessage(&msg);
  673. } else {
  674. if(counter++ == 10) {
  675. endTime = startTime;
  676. startTime = getTime();
  677. fps = counter * 1000.0f / (float)(startTime - endTime);
  678. counter = 0;
  679. }
  680. ifps = 1.0f / fps;
  681. idle();
  682. render();
  683. SwapBuffers(wglGetCurrentDC());
  684. mouseButton &= ~(BUTTON_UP | BUTTON_DOWN);
  685. }
  686. }
  687. }
  688. /*
  689.  */
  690. int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) {
  691. int argc = 1;
  692. char *argv[256];
  693. argv[0] = "none";
  694. while(*lpCmdLine && argc < 256) {
  695. while(*lpCmdLine && *lpCmdLine <= ' ') lpCmdLine++;
  696. if(*lpCmdLine) {
  697. argv[argc++] = lpCmdLine;
  698. while(*lpCmdLine && *lpCmdLine > ' ') lpCmdLine++;
  699. if(*lpCmdLine) *(lpCmdLine++) = 0;
  700. }
  701. }
  702. main(argc,argv);
  703. return 0;
  704. }
  705. #endif