Added support for 3Dconnexion Space Navigator.
authorJinrong Xie <jrxie@ucdavis.edu>
Mon, 29 Jun 2015 10:08:53 +0000 (10:08 +0000)
committerDiederick Niehorster <dcnieho@gmail.com>
Mon, 29 Jun 2015 10:08:53 +0000 (10:08 +0000)
(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
src/mswin/fg_internal_mswin.h
src/mswin/fg_main_mswin.c
src/mswin/fg_spaceball_mswin.c

index b1b321c..52d9841 100644 (file)
@@ -29,7 +29,7 @@ void fgInitialiseSpaceball(void)
 
     fgPlatformInitializeSpaceball();
 
-    sball_initialized = 1;
+    //sball_initialized = 1;
 }
 
 void fgSpaceballClose(void)
index 0fefb31..c5ef600 100644 (file)
@@ -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 );
 
index 54ec12c..97b8363 100644 (file)
@@ -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 );
index 3726389..4d96c31 100644 (file)
@@ -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 <karcaw at gmail.com>
  * Creation date: Sat Feb 4, 2012
  *
+ * Copyright (c) 2014 Jinrong Xie. All Rights Reserved.
+ * Written by Jinrong Xie <stonexjr at gmail.com>
+ * 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
  * 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 <GL/freeglut.h>
 #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