四、第一种方法尝试——自定义输入设备----->失败了
在vega中,可以使用自定义输入设备,如果自定义一个输入设备,通过windows操作JoyStick的API将JoyStick的各个轴数据放在自定义输入设备的Toggles和Sliders中,是不是可以达到模拟一个FlyBox的目的呢?相关vega函数代码如下:
[cpp]vgIDev *joyInput= vgNewIDev();
vgProp( joyInput, VGIDEV_DEVICETYPE, VGIDEV_USER_DEFINED );
vgIDevUserOpenFunc( joyInput, OpenFunc );
vgIDevUserReadFunc( joyInput, ReadFunc );
vgIDevUserCloseFunc( joyInput, CloseFunc );
vgIDevOpen ( joyInput );
int OpenFunc(vgIDevUserOpenStruct* openStruct)
{
openStruct->num_toggles = 8;
openStruct->num_sliders = 1;
return 1;
}
int ReadFunc(vgIDevUserReadStruct* readStruct)
{
int toggles[8];
Joy.GetJoystickData(); //Joy是我自己写的手柄操纵类的实例,后面有详细实现代码。
//读取JoyStick的各个按键的状态
if (Joy.Button1IsPressed())
toggles[0] = 1;
else
toggles[0] = 0;
if (Joy.Button2IsPressed())
toggles[1] = 1;
else
toggles[1] = 0;
if (Joy.Button3IsPressed())
toggles[2] = 1;
else
toggles[2] = 0;
if (Joy.Button4IsPressed())
toggles[3] = 1;
else
toggles[3] = 0;
if (Joy.Button5IsPressed())
toggles[4] = 1;
else
toggles[4] = 0;
if (Joy.Button6IsPressed())
toggles[5] = 1;
else
toggles[5] = 0;
if (Joy.Button7IsPressed())
toggles[6] = 1;
else
toggles[6] = 0;
if (Joy.Button8IsPressed())
toggles[7] = 1;
else
toggles[7] = 0;
//将节流阀数据放到自定义输入设备的Sliders[0]中
readStruct->sliders[0] = Joy.GetThrottle();
//将JoyStick的x,y,rudder数据放到自定义输入设备的Pos的X,Y,H分量上
vgPosVec( readStruct->pos, Joy.GetPosX(), Joy.GetPosY(), 0, Joy.GetRudder(), 0, 0 );
//按键状态到自定义输入设备的toggles中
for (i = 0; i < 8; i++)
readStruct->toggles[ i ] = toggles[ i ];
return 1;
}
int CloseFunc()
{
return 1;
}
windows操纵JoyStick有特定的API,为了使用方便和后期扩展,我自己定义了个类,如下:
//MyJoyStick.h
#include <windows.h>
#include <mmsystem.h>
#if !defined(MYJOYSTICK_H_INCLUDE)
#define MYJOYSTICK_H_INCLUDE
class MyJoystick
{
public:
MyJoystick(int);
int GetPosX();
int GetPosY();
int GetPosZ();
int GetPosR();
int GetPosU();
int GetPosV();
int GetPosPov();
float GetThrottle();
float GetRudder();
bool Button1IsPressed();
bool Button2IsPressed();
bool Button3IsPressed();
bool Button4IsPressed();
bool Button5IsPressed();
bool Button6IsPressed();
bool Button7IsPressed();
bool Button8IsPressed();
void GetJoystickData();
protected:
UINT jID;
JOYINFOEX jInfo;
JOYCAPS jCaps;
private:
int PosX;
int PosY;
int PosZ;
int PosR;
int PosU;
int PosV;
int PosPov;
bool Btn1IsPressed;
bool Btn2IsPressed;
bool Btn3IsPressed;
bool Btn4IsPressed;
bool Btn5IsPressed;
bool Btn6IsPressed;
bool Btn7IsPressed;
bool Btn8IsPressed;
};
#endif
//MyJoyStick.cpp
#include "stdafx.h"
#include "MyJoyStick.h"
#include "stdio.h"
#include <math.h>
MyJoystick::MyJoystick(int jid=1)
{
if (jid == 1)
jID = JOYSTICKID1;
else if (jid == 2)
jID = JOYSTICKID2;
else jID = 0;
joyGetDevCaps(jID, &jCaps, sizeof(jCaps));
PosX = 0;
PosY = 0;
PosZ = 0;
PosR = 0;
PosU = 0;
PosV = 0;
PosPov = 0;
Btn1IsPressed = false;
Btn2IsPressed = false;
Btn3IsPressed = false;
Btn4IsPressed = false;
Btn5IsPressed = false;
Btn6IsPressed = false;
Btn7IsPressed = false;
Btn8IsPressed = false;
}
int MyJoystick::GetPosX()
{
//GetJoystickData();
return PosX;
}
int MyJoystick::GetPosY()
{
//GetJoystickData();
return PosY;
}
int MyJoystick::GetPosZ()
{
//GetJoystickData();
return PosZ;
}
int MyJoystick::GetPosR()
{
//GetJoystickData();
return PosR;
}
int MyJoystick::GetPosU()
{
//GetJoystickData();
return PosU;
}
int MyJoystick::GetPosV()
{
//GetJoystickData();
return PosV;
}
int MyJoystick::GetPosPov()
{
//GetJoystickData();
return PosPov;
}
float MyJoystick::GetThrottle()
{
float th;
//GetJoystickData();
th = 1.0f - ((float)PosZ) / ((float)(jCaps.wZmax - jCaps.wZmin));
return th;
}
float MyJoystick::GetRudder()
{
float ru;
ru = 2.0f*(((float)PosR) / ((float)(jCaps.wRmax - jCaps.wRmin)) - 0.5f);
if (ru > 0 )
ru = abs(ru *10000) / 10000.0;
else
ru = -abs(ru *10000) / 10000.0;
return ru;
}
bool MyJoystick::Button1IsPressed()
{
//GetJoystickData();
return Btn1IsPressed;
}
bool MyJoystick::Button2IsPressed()
{
//GetJoystickData();
return Btn2IsPressed;
}
bool MyJoystick::Button3IsPressed()
{
//GetJoystickData();
return Btn3IsPressed;
}
bool MyJoystick::Button4IsPressed()
{
//GetJoystickData();
return Btn4IsPressed;
}
bool MyJoystick::Button5IsPressed()
{
//GetJoystickData();
return Btn5IsPressed;
}
bool MyJoystick::Button6IsPressed()
{
//GetJoystickData();
return Btn6IsPressed;
}
bool MyJoystick::Button7IsPressed()
{
//GetJoystickData();
return Btn7IsPressed;
}
bool MyJoystick::Button8IsPressed()
{
//GetJoystickData();
return Btn8IsPressed;
}
void MyJoystick::GetJoystickData()
{
MMRESULT res;
jInfo.dwSize = sizeof (jInfo);
jInfo.dwFlags = JOY_RETURNALL;
res = joyGetPosEx(jID, &jInfo);
if ( res== JOYERR_NOERROR)
{
PosX = jInfo.dwXpos;
PosY = jInfo.dwYpos;
PosZ = jInfo.dwZpos;
PosR = jInfo.dwRpos;
PosU = jInfo.dwUpos;
PosV = jInfo.dwVpos;
PosPov = jInfo.dwPOV / 100;
Btn1IsPressed = ((jInfo.dwButtons & JOY_BUTTON1) ? true : false);
Btn2IsPressed = ((jInfo.dwButtons & JOY_BUTTON2) ? true : false);
Btn3IsPressed = ((jInfo.dwButtons & JOY_BUTTON3) ? true : false);
Btn4IsPressed = ((jInfo.dwButtons & JOY_BUTTON4) ? true : false);
Btn5IsPressed = ((jInfo.dwButtons & JOY_BUTTON5) ? true : false);
Btn6IsPressed = ((jInfo.dwButtons & JOY_BUTTON6) ? true : false);
Btn7IsPressed = ((jInfo.dwButtons & JOY_BUTTON7) ? true : false);
Btn8IsPressed = ((jInfo.dwButtons & JOY_BUTTON8) ? true : false);
}
else
{
if (res == MMSYSERR_NODRIVER)
printf("MMSYSERR_NODRIVER\n");
if (res == MMSYSERR_INVALPARAM)
printf("MMSYSERR_INVALPARAM\n");
if (res == MMSYSERR_BADDEVICEID)
printf("MMSYSERR_BADDEVICEID\n");
if (res == JOYERR_UNPLUGGED)
printf("JOYERR_UNPLUGGED\n");
PosX = 0;
PosY = 0;
PosZ = 0;
PosR = 0;
PosU = 0;
PosV = 0;
PosPov = 0;
Btn1IsPressed = false;
Btn2IsPressed = false;
Btn3IsPressed = false;
Btn4IsPressed = false;
Btn5IsPressed = false;
Btn6IsPressed = false;
Btn7IsPressed = false;
Btn8IsPressed = false;
}
}
[/cpp]
经过试验,我发现,Filght Simulator运动模型,在使用自定义操作设备时,可以接收X,Y,H的输入数据,尾舵可以用了;但仍然存在问题,按钮我提供了8个,vega只接收前三个,节流阀我提供了,vega不接收。也就是说,这种自定义设备只比vega中的PC JoyStick设备多了个尾舵控制,其它没变化。
通过试验和分析,第一种方案失败了,但我也从中得到了一个结论:
vega中特定运动模型对不同输入设备,支持的输入数据是不同的。也就是说,FlyBox可以使用X、Y、H、Slider进行对Flight Simulator运动模型的控制,不是因为Flybox有这些输入,而是因为,只有输入设备是FlyBox时,Flight Simulator运动模型,才使用输入设备的X、Y、H、Slider进行控制。所以,我们虽然自定义了输入设备提供这些数据,但就是因为设备类型是VGIDEV_USER_DEFINED,而不是VGIDEV_FLYBOX,才失败了。
要使用JoyStick完全模拟FlyBox,自定义输入设备是没戏了,但真的没办法了么? |