Added support for 3Dconnexion Space Navigator.

This commit is contained in:
Jinrong Xie 2014-12-24 03:46:49 -08:00
parent b1316c651f
commit 857105a0b4
4 changed files with 154 additions and 5 deletions

View File

@ -29,7 +29,7 @@ void fgInitialiseSpaceball(void)
fgPlatformInitializeSpaceball(); fgPlatformInitializeSpaceball();
sball_initialized = 1; //sball_initialized = 1;
} }
void fgSpaceballClose(void) void fgSpaceballClose(void)

View File

@ -127,6 +127,12 @@ struct tagSFG_PlatformJoystick
#define FREEGLUT_MENU_PEN_HBACK_COLORS {0.15f, 0.15f, 0.45f, 1.0f} #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 */ /* Function to be called on exit */
extern void (__cdecl *__glutExitFunc)( int return_value ); extern void (__cdecl *__glutExitFunc)( int return_value );

View File

@ -1543,6 +1543,16 @@ LRESULT CALLBACK fgPlatformWindowProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPAR
break; break;
} }
#endif #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: default:
/* Handle unhandled messages */ /* Handle unhandled messages */
lRet = DefWindowProc( hWnd, uMsg, wParam, lParam ); lRet = DefWindowProc( hWnd, uMsg, wParam, lParam );

View File

@ -2,11 +2,15 @@
* fg_spaceball_mswin.c * fg_spaceball_mswin.c
* *
* Spaceball support for Windows * Spaceball support for Windows
* *
* Copyright (c) 2012 Stephen J. Baker. All Rights Reserved. * Copyright (c) 2012 Stephen J. Baker. All Rights Reserved.
* Written by Evan Felix <karcaw at gmail.com> * Written by Evan Felix <karcaw at gmail.com>
* Creation date: Sat Feb 4, 2012 * 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 * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation * 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 * 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. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
/* /*
* This code is a very complicated way of doing nothing. * This code is enhanced by at least supporting 3Dconnexion's
* But is needed for mswindows platform builds. * six degree of freedom navigator.
*/ */
#include <GL/freeglut.h> #include <GL/freeglut.h>
#include "../fg_internal.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) 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; return;
} }
@ -44,7 +79,7 @@ void fgPlatformSpaceballClose(void)
int fgPlatformHasSpaceball(void) int fgPlatformHasSpaceball(void)
{ {
return 0; return __fgSpaceball.hwndTarget ? 1 : 0;
} }
int fgPlatformSpaceballNumButtons(void) int fgPlatformSpaceballNumButtons(void)
@ -56,3 +91,101 @@ void fgPlatformSpaceballSetWindow(SFG_Window *window)
{ {
return; 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;
}
}
}