/* Raydium - CQFD Corp. http://raydium.org/ License: GPL - GNU General Public License, see "gpl.txt" file. */ #include "headers/myglut.h" #include #include static HINSTANCE currInstance; static HWND currWnd; static HDC currDC; static HGLRC currGLRC; LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); // ---------------------- public API void glutInit(int *argc, char **argv) { currInstance = NULL ; currWnd = NULL ; currDC = NULL ; currGLRC = NULL ; glutReshapeFuncCB=NULL; glutKeyboardFuncCB=NULL; glutSpecialUpFuncCB=NULL; glutSpecialFuncCB=NULL; glutMotionFuncCB=NULL; glutPassiveMotionFuncCB=NULL; glutMouseFuncCB=NULL; glutDisplayFuncCB=NULL; glutIdleFuncCB=NULL; _glutMouseVisible=1; } void mylgutCloseWindow(void) { wglMakeCurrent ( NULL, NULL ) ; wglDeleteContext ( currGLRC ) ; DestroyWindow ( currWnd ) ; } //glutSetCursor void glutSetCursor(int cursor) { switch(cursor) { case GLUT_CURSOR_LEFT_ARROW: if(_glutMouseVisible) break; ShowCursor(1); _glutMouseVisible=1; break; case GLUT_CURSOR_NONE: default: if(!_glutMouseVisible) break; ShowCursor(0); _glutMouseVisible=0; break; break; } //SetCursor( LoadCursor ( NULL, wcursor ) ) ; } //glutWarpPointer (move mouse) void glutWarpPointer(int x, int y) { POINT point; point.x = x; point.y = y; ClientToScreen(currWnd /* ? */, &point); SetCursorPos(point.x, point.y); } //glutSwapBuffers void glutSwapBuffers(void) { glFlush () ; SwapBuffers ( currDC ) ; } //glutMainLoop is generic (myglut.c) // ------------- private part void myglutGetEvents (void) { MSG msg; while ( PeekMessage( &msg, currWnd, 0, 0, PM_REMOVE ) ) { TranslateMessage( &msg ) ; DispatchMessage ( &msg ) ; } } void pwInit ( int x, int y, int w, int h, int multisample, char *title, int border, int num_samples ) { WNDCLASS wc; signed char fullscn; RECT rect; DWORD style = 0; int iPixelFormat; int origin [2] = { 0, 0 }; int size [2] = { 640, 480 }; PIXELFORMATDESCRIPTOR pfd; currInstance = GetModuleHandleA( NULL ) ; /* Register the window class */ wc.style = CS_OWNDC | CS_VREDRAW | CS_HREDRAW ; wc.lpfnWndProc = WndProc ; wc.cbClsExtra = 0 ; wc.cbWndExtra = 0 ; wc.hInstance = currInstance ; wc.hIcon = LoadIcon ( NULL, IDI_APPLICATION ) ; wc.hCursor = LoadCursor ( NULL, IDC_ARROW ) ; wc.hbrBackground = ( HBRUSH ) ( COLOR_WINDOW + 1 ) ; wc.lpszMenuName = NULL ; wc.lpszClassName = "RaydiumAppClass" ; if ( !RegisterClass( &wc ) ) { raydium_log("(my)glut: ERROR: Can't register window class" ) ; exit ( 1 ) ; } /* Setup window style */ fullscn = (w == -1 && h == -1 ) ? 1 : 0 ; if ( w == -1 ) w = GetSystemMetrics( SM_CXSCREEN ) ; if ( h == -1 ) h = GetSystemMetrics( SM_CYSCREEN ) ; if ( x == -1 ) x = (GetSystemMetrics( SM_CXSCREEN ) / 2) - (w/2) ; if ( y == -1 ) y = (GetSystemMetrics( SM_CYSCREEN ) / 2) - (h/2); origin [ 0 ] = x ; origin [ 1 ] = y ; size [ 0 ] = w ; size [ 1 ] = h ; rect.left = x ; rect.top = y ; rect.right = rect.left + w ; rect.bottom = rect.top + h ; if ( !fullscn ) style = WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS ; else style = WS_POPUP ; AdjustWindowRect( &rect, style, 0 ) ; /* Create the window */ currWnd = CreateWindow( "RaydiumAppClass", title, style, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, NULL, NULL, currInstance, NULL ) ; if ( !currWnd ) { raydium_log("(my)glut: ERROR: Can't create window" ) ; exit ( 1 ) ; } /* Get DC for this window */ currDC = GetDC ( currWnd ) ; if ( !currDC ) { raydium_log("(my)glut: ERROR: Can't get window DC" ) ; exit ( 1 ) ; } // wglGetExtensionsStringARBtype *wglGetExtensionsStringARB = (wglGetExtensionsStringARBtype *)wglGetProcAddress ( "wglGetExtensionsStringARB" ) ; // const char *extensionsString = wglGetExtensionsStringARB ( currDC ) ; // printf ( "%s %x %s\n", glGetString ( GL_EXTENSIONS ), wglGetExtensionsStringARB, extensionsString ) ; // if (!GLExtensionExists("WGL_ARB_multisample ")) // return suggestedFormat; pfd.nSize=sizeof(PIXELFORMATDESCRIPTOR); pfd.nVersion=1; pfd.dwFlags=PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType=PFD_TYPE_RGBA; pfd.cColorBits=24; pfd.cRedBits=0; pfd.cRedShift=0; pfd.cGreenBits=0; pfd.cGreenShift=0; pfd.cBlueBits=0; pfd.cBlueShift=0; pfd.cAlphaBits=0; pfd.cAlphaShift=0; pfd.cAccumBits=0; pfd.cAccumRedBits=0; pfd.cAccumGreenBits=0; pfd.cAccumBlueBits=0; pfd.cAccumAlphaBits=0; pfd.cDepthBits=32; pfd.cStencilBits=1; pfd.cAuxBuffers=0; pfd.iLayerType=PFD_MAIN_PLANE; pfd.bReserved=0; pfd.dwLayerMask=0; pfd.dwVisibleMask=0; pfd.dwDamageMask=0; /* Get best available match of pixel format for DC */ iPixelFormat = ChoosePixelFormat ( currDC, &pfd ) ; if ( iPixelFormat == 0 ) { raydium_log("(my)glut: ERROR: Can't get OpenGL pixel format" ) ; exit ( 1 ) ; } /* Set the pixel format of the DC */ if ( !SetPixelFormat( currDC, iPixelFormat, &pfd ) ) { raydium_log("(my)glut: ERROR: Can't set OpenGL pixel format" ) ; exit ( 1 ) ; } /* Show the window and paint its contents */ ShowWindow ( currWnd, SW_SHOW ) ; UpdateWindow ( currWnd ) ; /* Create openGL context and make it current */ currGLRC = wglCreateContext ( currDC ) ; if ( !currGLRC ) { raydium_log("(my)glut: ERROR: Unable to open a suitable window"); exit ( 1 ) ; } if ( !wglMakeCurrent ( currDC, currGLRC ) ) { raydium_log("(my)glut: ERROR: Unable to open a suitable window"); exit ( 1 ) ; } glClear ( GL_COLOR_BUFFER_BIT ) ; glutSwapBuffers () ; glClear ( GL_COLOR_BUFFER_BIT ) ; glutSwapBuffers () ; // if (glutReshapeFuncCB) // glutReshapeFuncCB(w, h); DescribePixelFormat(currDC, iPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd); raydium_log("Found %ix%i with %i bpp color and %i bits zbuffer (stencil is %i)",w,h,pfd.cColorBits,pfd.cDepthBits,pfd.cStencilBits); } LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { static int key = -1 ; static int updown = GLUT_UP ; static int old_key = -1 ; // We need this because "key" changes case int button = -1 ; static int mb = 0 ; static int lastx = 0 ; static int lasty = 0 ; BYTE state[256]; WORD code[2]; signed char b; signed char special=0; signed char repeating=0; int size[2]; switch (uMsg) { case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: updown = GLUT_DOWN ; if ( uMsg == WM_LBUTTONDOWN ) { button = GLUT_LEFT_BUTTON ; mb |= 1 ; } else if ( uMsg == WM_MBUTTONDOWN ) { button = GLUT_MIDDLE_BUTTON ; mb |= 2 ; } else { button = GLUT_RIGHT_BUTTON ; mb |= 4 ; } SetCapture ( hWnd ) ; lastx = (LOWORD( lParam ) ) ; lasty = (HIWORD( lParam ) ) ; if ( button != -1 && glutMouseFuncCB ) (*glutMouseFuncCB) ( button, updown, lastx, lasty ) ; break; case WM_LBUTTONUP: case WM_MBUTTONUP: case WM_RBUTTONUP: updown = GLUT_UP ; if ( uMsg == WM_LBUTTONUP ) { button = GLUT_LEFT_BUTTON ; mb &= ~1 ; } else if ( uMsg == WM_MBUTTONUP ) { button = GLUT_MIDDLE_BUTTON ; mb &= ~2 ; } else { button = GLUT_RIGHT_BUTTON ; mb &= ~4 ; } if ( mb == 0 ) ReleaseCapture () ; lastx = (LOWORD( lParam ) ) ; lasty = (HIWORD( lParam ) ) ; if ( button != -1 && glutMouseFuncCB ) (*glutMouseFuncCB) ( button, updown, lastx, lasty ) ; break; case WM_MOUSEMOVE: lastx = (LOWORD( lParam ) ); lasty = (HIWORD( lParam ) ); if ( glutPassiveMotionFuncCB ) (*glutPassiveMotionFuncCB) ( lastx, lasty ) ; break; case WM_MOUSEWHEEL: if ( ( short ) HIWORD( wParam ) > 0 ) { if ( glutPassiveMotionFuncCB ) (*glutMouseFuncCB) ( 3, GLUT_DOWN, lastx, lasty ) ; if ( glutPassiveMotionFuncCB ) (*glutMouseFuncCB) ( 3, GLUT_UP, lastx, lasty ) ; } else { if ( glutPassiveMotionFuncCB ) (*glutMouseFuncCB) ( 4, GLUT_DOWN, lastx, lasty ) ; if ( glutPassiveMotionFuncCB ) (*glutMouseFuncCB) ( 4, GLUT_UP, lastx, lasty ) ; } case WM_KEYDOWN: // If the key is already down, we are on auto-repeat. Break if the autorepeat is disabled. if ( ( updown == GLUT_DOWN ) && ( (int)wParam == old_key ) ) { /* if ( autoRepeat ) {*/ // Disable CTRL, SHIFT, CapsLock keys from making a callback if ( ( key == VK_CONTROL ) || ( key == VK_SHIFT ) || ( key == VK_CAPITAL ) ) break ; /* if ( key != -1 && kbCB ) // Autorepeat enabled, call the callback with an "up" setting (*kbCB) ( key, PW_UP, lastx, lasty ) ; } else*/ repeating=1; } updown = GLUT_DOWN ; old_key = wParam ; // FALLTHROUGH case WM_KEYUP: if ( uMsg == WM_KEYUP ) updown = GLUT_UP ; key = wParam ; // Disable CTRL, SHIFT, CapsLock keys from making a callback if ( ( key == VK_CONTROL ) || ( key == VK_SHIFT ) || ( key == VK_CAPITAL ) ) break ; switch ( key ) { case VK_F1: key = GLUT_KEY_F1; special=1; break; case VK_F2: key = GLUT_KEY_F2; special=1; break; case VK_F3: key = GLUT_KEY_F3; special=1; break; case VK_F4: key = GLUT_KEY_F4; special=1; break; case VK_F5: key = GLUT_KEY_F5; special=1; break; case VK_F6: key = GLUT_KEY_F6; special=1; break; case VK_F7: key = GLUT_KEY_F7; special=1; break; case VK_F8: key = GLUT_KEY_F8; special=1; break; case VK_F9: key = GLUT_KEY_F9; special=1; break; case VK_F10: key = GLUT_KEY_F10; special=1; break; case VK_F11: key = GLUT_KEY_F11; special=1; break; case VK_F12: key = GLUT_KEY_F12; special=1; break; case VK_LEFT: key = GLUT_KEY_LEFT; special=1; break; case VK_RIGHT: key = GLUT_KEY_RIGHT; special=1; break; case VK_UP: key = GLUT_KEY_UP; special=1; break; case VK_DOWN: key = GLUT_KEY_DOWN; special=1; break; case VK_PRIOR: key = GLUT_KEY_PAGE_UP; special=1; break; case VK_NEXT: key = GLUT_KEY_PAGE_DOWN; special=1; break; case VK_HOME: key = GLUT_KEY_HOME; special=1; break; case VK_END: key = GLUT_KEY_END; special=1; break; case VK_INSERT: key = GLUT_KEY_INSERT; special=1; break; default: // don't do this for WinCE b = GetKeyboardState( state ); assert(b); code [ 0 ] = 0; // WK: I need to do this, or on my Win2k box, the upper bits remain unchanged. if( ToAscii( key, 0, state, code, 0 ) == 1 ) if((0xFF00 & code[0]) == 0) // setting a high bit in key causes crashes later on (out of range array access) key=code[ 0 ]; } if ( key != -1) { // special down if(special && updown==GLUT_DOWN && glutSpecialFuncCB && !repeating) glutSpecialFuncCB(key,lastx,lasty); // special up if(special && updown==GLUT_UP && glutSpecialUpFuncCB && !repeating) glutSpecialUpFuncCB(key,lastx,lasty); // normal if(!special && updown==GLUT_DOWN && glutKeyboardFuncCB) glutKeyboardFuncCB(key,lastx,lasty); /*if(!special && repeating && glutKeyboardFuncCB) glutKeyboardFuncCB(key,lastx,lasty);*/ //(*kbCB) ( key, updown, lastx, lasty ) ; } break; case WM_SIZE: size[0] = LOWORD(lParam) ; size[1] = HIWORD(lParam) ; _glutWindowSize[0]=size[0]; _glutWindowSize[1]=size[1]; if (glutReshapeFuncCB) glutReshapeFuncCB(size[0], size[1]); break; case WM_CLOSE: exit(0); break; default: return ( DefWindowProc ( hWnd, uMsg, wParam, lParam ) ) ; } return 0; }