OPENNI实践-体感方向盘玩赛车游戏

为了实现利用体感进行方向盘模拟,我们首先要明白,方向盘是一个线性的虚拟手柄,因为玩家在进行不同的旋转操作的时候,会有不同的角度,在这种情况下,我们需要反映成游戏中不同的拐弯角度。而不是像按键手柄,一个按钮实现一个功能。在这里我们使用线性手柄的轴度,模拟线性方向盘的感觉,但是在这里我们只实现与虚拟手柄的通信,而不是创建虚拟手柄。

在这里我们使用四轴虚拟线性手柄,但是因为只需要两个轴,所以我们只用两个。一个控制转角,一个控制油门。

这里的难点其实在于如何去与虚拟线性手柄进行通讯,这里,我们使用了USBHID,也就是一种USB通讯协议,我们常用的鼠标,键盘,手柄之类的外设一般通过这个来进行驱动,从而进行控制。USB HID类是比较大的一个类,HID类设备属于人机交互操作的设备。用于控制计算机操作的一些方面,如USB鼠标,USB键盘,USB游戏操纵杆,USB触摸板,USB轨迹球、电话拨号设备、VCR遥控等等设备。另外,使用HID设备的一个好处就是,操作系统自带了HID类的驱动程序,而用户无需去开发很麻烦的驱动程序,只要直接使用API调用即可完成通信。所以很多简单的USB设备,喜欢枚举成HID设备,这样就可以不用安装驱动而直接使用。
具体关于USBHID的详细信息,可以参考博文http://blog.csdn.net/leo_wonty/article/details/6721214。

但是我们如何进行USBHID的通讯,在这里我们使用的是DDK,win DDK是微软官方出的专门用于驱动编写的sdk。下载与安装都很简单,https://www.microsoft.com/en-us/download/details.aspx?id=11800在这里下载,下载之后点击setup的那个就可以了。然后就安装好了。当然,由于我们要实现的功能不需要那么多库文件,所以我们也可以单独下载所需要的头文件和链接库。

接下来是代码部分:

HANDLE OpenContorlDevice()
{
	HDEVINFO hardwareDeviceInfo;
	SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
	SP_DEVICE_INTERFACE_DATA devInfoData;
	GUID hidguid;
	PSP_DEVICE_INTERFACE_DETAIL_DATA deviceInterfaceDetailData=NULL;
	DWORD predictedLength=0;
	DWORD requiredLength=0;
	HANDLE file=INVALID_HANDLE_VALUE;
	PHIDP_PREPARSED_DATA Ppd=NULL;
	HIDD_ATTRIBUTES Attributes;
	HIDP_CAPS Caps;
	int i;

	HidD_GetHidGuid(&hidguid);
	hardwareDeviceInfo=SetupDiGetClassDevs((LPGUID)&hidguid,NULL,NULL,(DIGCF_PRESENT|DIGCF_INTERFACEDEVICE));

	if (INVALID_HANDLE_VALUE==hardwareDeviceInfo)
	{
		printf("SertupDiGetClassDevs failed:",GetLastError());
		goto cleanup;
	}

	deviceInterfaceData.cbSize=sizeof(SP_DEVICE_INTERFACE_DATA);
	devInfoData.cbSize=sizeof(SP_DEVINFO_DATA);

	for (i=0;SetupDiEnumDeviceInterfaces(hardwareDeviceInfo,0,(LPGUID)&hidguid,i,&deviceInterfaceData);i++)
	{
		SetupDiGetDeviceInterfaceDetail(hardwareDeviceInfo,&deviceInterfaceData,NULL,0,&requiredLength,NULL);
		predictedLength=requiredLength;
		deviceInterfaceDetailData=(PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(predictedLength);

		if (!deviceInterfaceDetailData)
		{
			printf("Error: OpenDeviceInterface:malloc faild\n");
			goto cleanup;
		}

		deviceInterfaceDetailData->cbSize=sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

		if (!SetupDiGetDeviceInterfaceDetail(hardwareDeviceInfo,&deviceInterfaceData,deviceInterfaceDetailData,predictedLength,&requiredLength,NULL))
		{
			printf("Error: SetupDiGetInterfaceDeviceDetail failed: %x\r\n",GetLastError());
			goto cleanup;
		}

		file=CreateFile(deviceInterfaceDetailData->DevicePath,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
		if (INVALID_HANDLE_VALUE==file)
		{
			printf("Error:Creat file failed:%d\r\n",GetLastError());
			CloseHandle(file);
		}
		else
		{
			if (!HidD_GetPreparsedData(file,&Ppd))
			{
				printf("Error: HidD_GetPreparsedData failed\r\n");
				file=INVALID_HANDLE_VALUE;
			}
			else
			{
				if (!HidD_GetAttributes(file,&Attributes))
				{
					printf("Error: HidD_GetAttributes failed\r\n");
					file=INVALID_HANDLE_VALUE;
				}
				else
				{
					if (Attributes.VendorID==0x045E&&Attributes.ProductID==0x02AE)
					{
						if (!HidP_GetCaps(Ppd,&Caps))
						{
							printf("Error:HidP_GetCaps failed\r\n");
							file=INVALID_HANDLE_VALUE;
						}
						else
						{
							if ((Caps.UsagePage==0x09)&&(Caps.Usage==0x00))
							{
								printf("Success:Found my device..\r\n");
								goto cleanup;
							}
						}
					}
					else
					{
						printf("Error: VendorID or ProductID is not what we want\r\n");
						file=INVALID_HANDLE_VALUE;
					}
				}
			}
		}
		free(deviceInterfaceDetailData);
	}
	cleanup:
	if (Ppd!=NULL)
	{
		HidD_FreePreparsedData(Ppd);
	}
	SetupDiDestroyDeviceInfoList(hardwareDeviceInfo);
	return file;
}
在这里,我大概说一下这些代码所进行的流程,总的来说就是枚举设备,再打开设备,由于在这个过程中涉及到设备的描述符等参数,大家可以稍微了解一下。要与USB设备通信,就要先获取你的USB设备类的 GUID标识,然后再根据GUID来枚举该类的设备,然后从中找到你的设备。

首先,获取本系统中HID类的GUID标识,准备查找符合HID规范的USB设备,若找到了一个USB设备,则找到设备后则以读写的方式打开以进行操作,获取该设备的细节信息,然后根据VendorID 和 ProductID判断是否是目标设备。在这里我们需要注意的就是
VendorID 和 ProductID以及USAGE和USAGEPAPER这四个参数,一定要对应好虚拟手柄上的设备参数。

所需要的头文件为:

#include <stdio.h>
#include <windows.h>

extern "C" {
#include "hidsdi.h"
#include "setupapi.h"
}
#pragma comment (lib,"hid.lib")
#pragma comment (lib,"setupapi.lib")
#pragma comment (lib,"kernel32.lib")


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值