From cae6701c343e3a42bc9504f14e6d83e4ca9d8119 Mon Sep 17 00:00:00 2001 From: Jinrong Xie Date: Mon, 29 Jun 2015 10:08:53 +0000 Subject: [PATCH] Added support for 3Dconnexion Space Navigator. (cherry picked from commit 857105a0b4a4c44fcdd9b11a33eff0c910ce41a9) (cherry picked from commit 857105a0b4a4c44fcdd9b11a33eff0c910ce41a9) git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@1759 7f0cb862-5218-0410-a997-914c9d46530a --- src/fg_spaceball.c | 2 +- src/mswin/fg_internal_mswin.h | 6 ++ src/mswin/fg_main_mswin.c | 10 +++ src/mswin/fg_spaceball_mswin.c | 141 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 154 insertions(+), 5 deletions(-) diff --git a/src/fg_spaceball.c b/src/fg_spaceball.c index b1b321c..52d9841 100644 --- a/src/fg_spaceball.c +++ b/src/fg_spaceball.c @@ -29,7 +29,7 @@ void fgInitialiseSpaceball(void) fgPlatformInitializeSpaceball(); - sball_initialized = 1; + //sball_initialized = 1; } void fgSpaceballClose(void) diff --git a/src/mswin/fg_internal_mswin.h b/src/mswin/fg_internal_mswin.h index 0fefb31..c5ef600 100644 --- a/src/mswin/fg_internal_mswin.h +++ b/src/mswin/fg_internal_mswin.h @@ -127,6 +127,12 @@ struct tagSFG_PlatformJoystick #define FREEGLUT_MENU_PEN_HBACK_COLORS {0.15f, 0.15f, 0.45f, 1.0f} +/* -- PRIVATE FUNCTION DECLARATIONS ---------------------------------------- */ +/* Spaceball device functions, defined in fg_spaceball_mswin.c */ +//Added by Jinrong Xie (stonexjr @ gmail.com) 12/24/2014 +int fgIsSpaceballWinEvent(HWND hwnd, WPARAM wParam, LPARAM lParam); +void fgSpaceballHandleWinEvent(HWND hwnd, WPARAM wParam, LPARAM lParam); + /* Function to be called on exit */ extern void (__cdecl *__glutExitFunc)( int return_value ); diff --git a/src/mswin/fg_main_mswin.c b/src/mswin/fg_main_mswin.c index 54ec12c..97b8363 100644 --- a/src/mswin/fg_main_mswin.c +++ b/src/mswin/fg_main_mswin.c @@ -1543,6 +1543,16 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR break; } #endif + //Added by Jinrong Xie (stonexjr@gmail.com) 12/24/2014 + //for SpaceNavigator support on Windows. + /* + case WM_ACTIVATEAPP: + fgInitialiseSpaceball(); + break; + */ + case WM_INPUT: + fgSpaceballHandleWinEvent(hWnd, wParam, lParam); + break; default: /* Handle unhandled messages */ lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); diff --git a/src/mswin/fg_spaceball_mswin.c b/src/mswin/fg_spaceball_mswin.c index 3726389..4d96c31 100644 --- a/src/mswin/fg_spaceball_mswin.c +++ b/src/mswin/fg_spaceball_mswin.c @@ -2,11 +2,15 @@ * fg_spaceball_mswin.c * * Spaceball support for Windows - * + * * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. * Written by Evan Felix * Creation date: Sat Feb 4, 2012 * + * Copyright (c) 2014 Jinrong Xie. All Rights Reserved. + * Written by Jinrong Xie + * Modification date: Wed Dec 24, 2014 + * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation @@ -24,16 +28,47 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + /* - * This code is a very complicated way of doing nothing. - * But is needed for mswindows platform builds. + * This code is enhanced by at least supporting 3Dconnexion's + * six degree of freedom navigator. */ #include #include "../fg_internal.h" +enum { + SPNAV_EVENT_ANY, + SPNAV_EVENT_MOTION_TRANSLATION, + SPNAV_EVENT_MOTION_ROTATION, + SPNAV_EVENT_BUTTON /* includes both press and release */ +}; + +extern int sball_initialized; +unsigned int __fgSpaceKeystate = 0; +RAWINPUTDEVICE __fgSpaceball = { 0x01, 0x08, 0x00, 0x00 }; + void fgPlatformInitializeSpaceball(void) { + HWND hwnd; + sball_initialized = 1; + if (!fgStructure.CurrentWindow) + { + sball_initialized = 0; + return; + } + hwnd = fgStructure.CurrentWindow->Window.Handle; + + BOOL ok; + UINT cbSize = sizeof(__fgSpaceball); + __fgSpaceball.hwndTarget = hwnd; + ok = RegisterRawInputDevices(&__fgSpaceball, 1, cbSize); + + if (!ok){ + __fgSpaceball.hwndTarget = NULL; + sball_initialized = 0; + } + return; } @@ -44,7 +79,7 @@ void fgPlatformSpaceballClose(void) int fgPlatformHasSpaceball(void) { - return 0; + return __fgSpaceball.hwndTarget ? 1 : 0; } int fgPlatformSpaceballNumButtons(void) @@ -56,3 +91,101 @@ void fgPlatformSpaceballSetWindow(SFG_Window *window) { return; } + +int fgIsSpaceballWinEvent(HWND hwnd, WPARAM wParam, LPARAM lParam) +{ +} + +void fgSpaceballHandleWinEvent(HWND hwnd, WPARAM wParam, LPARAM lParam) +{ + #define LOGITECH_VENDOR_ID 0x46d + HRAWINPUT hRawInput = (HRAWINPUT)lParam; + UINT inputCode = (UINT)wParam; + RAWINPUTHEADER hdr; + UINT size; + BYTE *rawInputBuffer; + PRAWINPUT pRawInput; + UINT res; + RID_DEVICE_INFO sRidDeviceInfo; + + if (!sball_initialized) + { + fgPlatformInitializeSpaceball(); + if (!sball_initialized) + { + return; + } + } + + res = GetRawInputData(hRawInput, RID_INPUT, NULL, &size, sizeof(RAWINPUTHEADER)); + if (res == -1) + return; + + rawInputBuffer = (BYTE*)malloc(size); + pRawInput = (PRAWINPUT)rawInputBuffer; + + res = GetRawInputData(hRawInput, RID_INPUT, pRawInput, &size, sizeof(RAWINPUTHEADER)); + if (res == -1) + return; + if (pRawInput->header.dwType != RIM_TYPEHID) + return; + + sRidDeviceInfo.cbSize = sizeof(RID_DEVICE_INFO); + size = sizeof(RID_DEVICE_INFO); + res = GetRawInputDeviceInfo(pRawInput->header.hDevice, RIDI_DEVICEINFO, &sRidDeviceInfo, &size); + if (res == -1) + return; + + SFG_Window* window = fgWindowByHandle(hwnd); + if ((window == NULL)) + return; + + if (sRidDeviceInfo.hid.dwVendorId == LOGITECH_VENDOR_ID) + { + // Motion data comes in two parts: motion type and + // displacement/rotation along three axis. + // Orientation is a right handed coordinate system with + // X goes right, Y goes up and Z goes towards viewer, e.g. + // the one used in OpenGL + if (pRawInput->data.hid.bRawData[0] == + SPNAV_EVENT_MOTION_TRANSLATION)//0x01) + { // Translation vector + short* pnData = (short*)(&pRawInput->data.hid.bRawData[1]); + short X = pnData[0]; + short Y = -pnData[2]; + short Z = pnData[1]; + INVOKE_WCB(*window, SpaceMotion, (X, Y, Z)); + } + else if (pRawInput->data.hid.bRawData[0] == + SPNAV_EVENT_MOTION_ROTATION)//0x02) + { // Axis aligned rotation vector + short* pnData = (short*)(&pRawInput->data.hid.bRawData[1]); + short rX = pnData[0]; + short rY = -pnData[2]; + short rZ = pnData[1]; + INVOKE_WCB(*window, SpaceRotation, (rX, rY, rZ)); + } + else if (pRawInput->data.hid.bRawData[0] == + SPNAV_EVENT_BUTTON)//0x03) + { // State of the keys + unsigned long dwKeystate = *(unsigned long*)(&pRawInput->data.hid.bRawData[1]); + unsigned int state = GLUT_UP; + if (FETCH_WCB(*window, SpaceButton)) + { + int i; + for (i = 0; i < 32; i++) + { + unsigned long stateBefore = __fgSpaceKeystate&(1 << i); + unsigned long stateNow = dwKeystate&(1 << i); + + if (stateBefore && !stateNow) + INVOKE_WCB(*window, SpaceButton, (stateBefore, GLUT_DOWN)); + if (!stateBefore && stateNow) + INVOKE_WCB(*window, SpaceButton, (stateNow, GLUT_UP)); + + } + } + __fgSpaceKeystate = dwKeystate; + } + } +} \ No newline at end of file -- 1.7.10.4