Skip to content
Snippets Groups Projects
Commit 42a826c7 authored by Gilles Marckmann's avatar Gilles Marckmann
Browse files

Implementation of gamepad for Windows. Now the use of gamepad is available for...

Implementation of gamepad for Windows. Now the use of gamepad is available for Linux and Windows. Still to be done for Apple.

Very usefull for shell model with compartments (boat, plane, building,...). Allows a good immersion into the model. I advise you to test.

Rendering seems to be better on Linux than on Windows: residual offsets on some axes signals are observed which leads to a possible little drifting of the model. Needs to shake joystick. It may come from the gamepad I used which is a old one.

parent 29da1fdd
Branches
Tags
No related merge requests found
...@@ -4,194 +4,275 @@ ...@@ -4,194 +4,275 @@
// bugs and problems to the public mailing list <gmsh@geuz.org>. // bugs and problems to the public mailing list <gmsh@geuz.org>.
// //
// Contributed by Gilles Marckmann <gilles.marckmann@ec-nantes.fr> // Contributed by Gilles Marckmann <gilles.marckmann@ec-nantes.fr>
// default map is "THRUSTMASTER FireStorm Dual Power"-like
//
// ###### ######
// # but5 # # but7 #
// .########.. ..#######.
// ............ .......... .
// ...#######... ...########..
// ..# but4 #... ...# but6 #..
// ...########....... ........#########..
// .................... .....................
// .......#................... ..........................
// ......axis5..........................................####.......
// ........ #...........................................# b3 #.......
// ..........#...........................................# #.......
// ...###< axis4 >###...............................####..####..####...
// ...........#.....................................# b1 #......# b2 #...
// ............#.....................................# #......# #....
// ............#......................................####........####.....
// .............#.............................................####...........
// ..........................................................# b0 #..........
// ...........................................................# #...........
// .......................#######................#######.......####............
// ......................# axis1 ##............## axis3 ##......................
// .....................## | ##..........## | ##.....................
// ......................#<--axis0-->#..........#<--axis2--> #.....................
// ......................## | ##. .####. .## | ##......................
// .......................## | ##.. # b9 #...## | ##.......................
// ..........................#######......####......#######.........................
// ..................................................................................
// ..................... .......... ......... .....................
// .................... ....................
// .................. ..................
// .................. ..................
// .................. .................
// ................. ................
// ................ ...............
// .............. ..............
// ............. ............
// ............ ............
// .......... ..........
// ....... ........
// .... ...
//
#include <cstring>
#include <string>
#include <iostream>
#include <stdio.h>
#include "GamePad.h"
#include "Context.h"
#include <unistd.h>
#if defined(WIN32)
#include <math.h>
#endif
GamePad::GamePad() : active(false), frequency(.01), gamepad_fd(0) {
#if defined(WIN32)
for (int i = JOYSTICKID1 ; i < JOYSTICKID2 ; i++) {
if(JOYERR_NOERROR == joyGetDevCaps(i, &caps, sizeof(JOYCAPS)) ) {
/*
std::cout << "Joystick/Gamepad detected: "<< name ;
std::cout << " ( " << (int)caps.wNumAxes <<" axes /" ;
std::cout << (int)caps.wNumButtons <<" buttons)" << std::endl;
std::cout << " Driver name ....... " << caps.szPname << std::endl;
std::cout << " Manufacturer ID ... " << caps.wMid << std::endl;
std::cout << " Product ID ........ " << caps.wPid << std::endl;
std::cout << " RegKey ............ " << caps.szRegKey << std::endl;
std::cout << " OEMVxD ............ " << caps.szOEMVxD << std::endl;
std::cout << " wXmin ............. " << caps.wXmin << std::endl;
std::cout << " wXmax ............. " << caps.wXmax << std::endl;
std::cout << " wYmin ............. " << caps.wYmin << std::endl;
std::cout << " wYmax ............. " << caps.wYmax << std::endl;
std::cout << " wZmin ............. " << caps.wZmin << std::endl;
std::cout << " wZmax ............. " << caps.wZmax << std::endl;
std::cout << " wPeriodMin ........ " << caps.wPeriodMin << std::endl;
std::cout << " wPeriodMax ........ " << caps.wPeriodMax << std::endl;
std::cout << " wRmin ............. " << caps.wRmin << std::endl;
std::cout << " wRmax ............. " << caps.wRmax << std::endl;
std::cout << " wUmin ............. " << caps.wUmin << std::endl;
std::cout << " wUmax ............. " << caps.wUmax << std::endl;
std::cout << " wVmin ............. " << caps.wVmin << std::endl;
std::cout << " wVmax ............. " << caps.wVmax << std::endl;
*/
if(( 1./frequency <(double)caps.wPeriodMin ) ||( 1./frequency >(double)caps.wPeriodMax )){
frequency=.1/(double)caps.wPeriodMin;
}
gamepad_fd =i;
axes=std::min(GP_AXES,(int)caps.wNumAxes +2);
buttons=std::min(GP_BUTTONS,(int)caps.wNumButtons);
for (int i=0;i<buttons;i++) button[i]=false;
for (int i=0;i<axes;i++) axe[i]=0.;
active = true;
}
}
for (int i=0;i<buttons;i++) button[i]=0;
for (int i=0;i<axes;i++) axe[i]=0;
joyGetPosEx( gamepad_fd,&infoex) ;
infoex.dwFlags = JOY_RETURNALL;
#else
#if defined(__APPLE__)
// ??
#else // LINUX
gamepad_fd = open(GAMEPAD_DEV, O_RDONLY | O_NONBLOCK);
if (gamepad_fd > 0) {
ioctl(gamepad_fd, JSIOCGNAME(256), name);
ioctl(gamepad_fd, JSIOCGVERSION, &version);
ioctl(gamepad_fd, JSIOCGAXES, &axes);
ioctl(gamepad_fd, JSIOCGBUTTONS, &buttons);
std::cout << "Joystick/Gamepad detected: " << name ;
std::cout << " (version " << version << " / " ;
std::cout << (int)axes <<" axes /" ;
std::cout << (int)buttons <<" buttons)" << std::endl;
active = true;
}
#endif //(__APPLE__)
#endif //(WIN32)
for (int i=0;i<std::min(9,(int)buttons);i++) button_map[i]=i;
for (int i=0;i<std::min(7,(int)axes);i++) axe_map[i]=i;
axe_map[6]=1;
// another recognized map "Thrustmaster Run'N' Drive Wireless PS3"
// warning :: on Windows we dont have the human-friendly Model Name of the Gamepad
if ( strcmp(name,"Thrustmaster Run'N' Drive Wireless PS3" ) == 0){
button_map[0]=1;
button_map[1]=0;
button_map[5]=6;
button_map[6]=5;
}
}
GamePad::~GamePad() {
active = false;
gamepad_fd = 0;
#if !defined(WIN32)
#if !defined(__APPLE__)
close(gamepad_fd);
#endif //!(__APPLE__)
#endif //!(WIN32)
}
bool GamePad::toggle(const int _nbut) {
bool res;
if( toggle_status[_nbut] ){ res = true; toggle_status[_nbut]=false;}
else { res=false; }
return res;
}
int GamePad::read_event() {
#if defined(WIN32)
infoex.dwFlags = JOY_RETURNALL;
joyGetPosEx( gamepad_fd,&infoex) ;
axe[0]=(double)(( 1.*infoex.dwXpos-32767.)/32767.);
axe[1]=(double)(( 1.*infoex.dwYpos-32767.)/32767.);
axe[2]=(double)(( 1.*infoex.dwRpos-32767.)/32767.);
axe[3]=(double)(( 1.*infoex.dwZpos-32767.)/32767.);
if (infoex.dwPOV < 38000. ) {
double alpha = 3.14159/18000.* infoex.dwPOV;
axe[4]=1.001*sin(alpha); axe[5]=-1.001*cos(alpha);
}
else{
axe[4]= axe[5]=0.;
}
for (int i=0;i<6;i++) if ( fabs( axe[i]) < .01) axe[i]=0.;
bool event=false;
int event_num;
bool event_value;
for (int i=0;i<buttons;i++){
int bin=pow(2,i);
if( button[i] != (bool)(infoex.dwButtons & bin) ) {
event=true;
event_num=i;
event_value=(bool)(infoex.dwButtons & bin);
}
}
if(event){
if( button[event_num]==0 && event_value ) { toggle_status[event_num]=true; }
button[event_num]= event_value;
}
/*
std::cout<< "--------------------" << std::endl;
std::cout<< infoex.dwXpos << std::endl;
std::cout<< infoex.dwYpos << std::endl;
std::cout<< infoex.dwZpos << std::endl;
std::cout<< infoex.dwRpos << std::endl;
std::cout<< infoex.dwUpos << std::endl;
std::cout<< infoex.dwVpos << std::endl;
std::cout<< infoex.dwButtons << std::endl;
std::cout<< infoex.dwButtonNumber << std::endl;
std::cout<< infoex.dwPOV << std::endl;
*/
#else
#if defined(__APPLE__)
// ??
#else // LINUX
int result = read(gamepad_fd, &event, sizeof(event)) ;
if (result > 0) {
switch (event.type) {
case JS_EVENT_INIT:
break;
case JS_EVENT_INIT | JS_EVENT_AXIS:
break;
case JS_EVENT_INIT | JS_EVENT_BUTTON:
break;
case JS_EVENT_AXIS:
axe[(int)event.number]=(double)event.value/32767. ;
break;
case JS_EVENT_BUTTON:
if(button[(int)event.number]==0. && (bool)event.value) { toggle_status[(int)event.number]=true; }
button[(int)event.number]=(bool)event.value ;
break;
default:
break;
}
}
#endif //(__APPLE__)
#endif //(WIN32)
return 1;
}
void GamePad::affiche() {
for (int i=0;i<6;i++) std::cout<<("_________");
std::cout<<std::endl; std::cout<<" axis ";
for (int i=0;i<6;i++) std::cout<<" | "<<i;
std::cout<<std::endl; std::cout<<" ";
for (int i=0;i<6;i++) std::cout<<" | "<< axe[i] ;
std::cout<<std::endl;
for (int i=0;i<10;i++) std::cout<< ("_____");
std::cout<<std::endl; std::cout<<" b.";
for (int i=0;i<10;i++) std::cout<<" | "<<i;
std::cout<<std::endl; std::cout<<" ";
for (int i=0;i<10;i++) std::cout<<" | "<<button[i];
std::cout<<std::endl;
for (int i=0;i<10;i++) std::cout<< ("_____");
std::cout<<std::endl;
}
#if defined(WIN32) || defined(__APPLE__)
#include <cstring>
#include <string>
#include <iostream>
#include <stdio.h>
#include "GamePad.h"
GamePad::GamePad() : active(false), frequency(.01), gamepad_fd(0) {
for (int i=0;i<9;i++) button_map[i]=i;
for (int i=0;i<7;i++) axe_map[i]=i;
axe_map[6]=1;
// other recognized map "Thrustmaster Run'N' Drive Wireless PS3"
if ( strcmp(name,"Thrustmaster Run'N' Drive Wireless PS3" ) == 0){
button_map[0]=1;
button_map[1]=0;
button_map[5]=6;
button_map[6]=5;
}
}
GamePad::~GamePad() { gamepad_fd = 0;}
bool GamePad::toggle(const int _nbut) {
bool res;
if( toggle_status[_nbut] ){ res = true; toggle_status[_nbut]=false;}
else { res=false; }
return res;
}
int GamePad::read_event() { return 1;}
void GamePad::affiche() {}
#else // if !win32 => if linux/apple
#include <cstring>
#include <string>
#include <iostream>
#include <stdio.h>
#include "GamePad.h"
#include "Context.h"
#include <unistd.h>
GamePad::GamePad() : active(false), frequency(.01), gamepad_fd(0) {
gamepad_fd = open(GAMEPAD_DEV, O_RDONLY | O_NONBLOCK);
if (gamepad_fd > 0) {
ioctl(gamepad_fd, JSIOCGNAME(256), name);
ioctl(gamepad_fd, JSIOCGVERSION, &version);
ioctl(gamepad_fd, JSIOCGAXES, &axes);
ioctl(gamepad_fd, JSIOCGBUTTONS, &buttons);
std::cout << "Joystick/Gamepad detected: " << name ;
std::cout << " (version " << version << " / " ;
std::cout << (int)axes <<" axes /" ;
std::cout << (int)buttons <<" buttons)" << std::endl;
active = true;
}
// default map is "THRUSTMASTER FireStorm Dual Power"-like
//
// ###### ######
// # but5 # # but7 #
// .########.. ..#######.
// ............ .......... .
// ...#######... ...########..
// ..# but4 #... ...# but6 #..
// ...########....... but9 but10........#########..
// .................... .....................
// .......#................... ..........................
// ......axis5..........................................####.......
// ........ #...........................................# b3 #.......
// ..........#...........................................# #.......
// ...###< axis4 >###...............................####..####..####...
// ...........#.....................................# b1 #......# b2 #...
// ............#.....................................# #......# #....
// ............#......................................####........####.....
// .............#.............................................####...........
// ..........................................................# b0 #..........
// ...........................................................# #...........
// .......................#######................#######.......####............
// ......................# axis1 ##............## axis3 ##......................
// .....................## | ##..........## | ##.....................
// ......................#<--axis0-->#..........#<--axis2--> #.....................
// ......................## | ##. .####. .## | ##......................
// .......................## | ##.. # b8 #...## | ##.......................
// ..........................#######......####......#######.........................
// ..................................................................................
// ..................... .......... ......... .....................
// .................... ....................
// .................. ..................
// .................. ..................
// .................. .................
// ................. ................
// ................ ...............
// .............. ..............
// ............. ............
// ............ ............
// .......... ..........
// ....... ........
// .... ...
//
for (int i=0;i<9;i++) button_map[i]=i;
for (int i=0;i<7;i++) axe_map[i]=i;
axe_map[6]=1;
// other recognized map "Thrustmaster Run'N' Drive Wireless PS3"
if ( strcmp(name,"Thrustmaster Run'N' Drive Wireless PS3" ) == 0){
button_map[0]=1;
button_map[1]=0;
button_map[5]=6;
button_map[6]=5;
}
}
GamePad::~GamePad() {
if (gamepad_fd > 0) { active = false; close(gamepad_fd); }
gamepad_fd = 0;
}
bool GamePad::toggle(const int _nbut) {
bool res;
if( toggle_status[_nbut] ){ res = true; toggle_status[_nbut]=false;}
else { res=false; }
return res;
}
int GamePad::read_event() {
int result = read(gamepad_fd, &event, sizeof(event)) ;
if (result > 0)
{
// time( &rawtime );
switch (event.type)
{
case JS_EVENT_INIT:
break;
case JS_EVENT_INIT | JS_EVENT_AXIS:
break;
case JS_EVENT_INIT | JS_EVENT_BUTTON:
break;
case JS_EVENT_AXIS:
// std::cout<< "------"<<rawtime<<"---- " <<std::endl;
axe[(int)event.number]=(double)event.value/32767. ;
break;
case JS_EVENT_BUTTON:
// std::cout<< "------"<<rawtime<<"---- " <<std::endl;
if(button[(int)event.number]==0. && (bool)event.value)
{ toggle_status[(int)event.number]=true; }
button[(int)event.number]=(bool)event.value ;
break;
default:
break;
}
}
// std::cout<< "------"<<rawtime<<"---- " <<std::endl;
// else if (event_read){changed=false;}
return 1;
}
void GamePad::affiche() {
// printf ("----------------------------------------------\n");
for (int i=0;i<axes;i++) printf ("___________");
printf ("\n");
for (int i=0;i<axes;i++) printf (" axis %2d |",i);
printf ("\n");
for (int i=0;i<axes;i++) printf (" %7f |", axe[i] );
printf ("\n");
for (int i=0;i<buttons;i++) printf ("_______");
printf ("\n");
for (int i=0;i<buttons;i++) printf (" b.%2d |",i);
printf ("\n");
for (int i=0;i<buttons;i++) printf (" %4d |",button[i]);
printf ("\n");
for (int i=0;i<buttons;i++) printf ("_______");
printf ("\n");
}
#endif // win32
...@@ -14,70 +14,62 @@ ...@@ -14,70 +14,62 @@
#define GP_AXES 6 #define GP_AXES 6
#if defined(WIN32)
#if defined(WIN32) || defined(__APPLE__) #include <windows.h>
#include <mmsystem.h>
class GamePad { #else
public: #if defined(__APPLE__)
bool active; // ??
bool toggle_status[GP_BUTTONS]; #else // LINUX
bool event_read; #include <linux/joystick.h>
double frequency; #include <fcntl.h>
GamePad(); #define GAMEPAD_DEV "/dev/input/js0"
~GamePad(); #endif
double axe[GP_AXES]; #endif
bool button[GP_BUTTONS];
bool toggle(const int _nbut); class GamePad {
int read_event(); public:
void affiche(); bool active;
int button_map[10]; bool toggle_status[GP_BUTTONS];
int axe_map[8]; bool event_read;
private: double frequency;
int gamepad_fd; GamePad();
// js_event event; ~GamePad();
// __u32 version; double axe[GP_AXES];
// __u8 axes; bool button[GP_BUTTONS];
// __u8 buttons; bool toggle(const int _nbut);
char name[256]; int read_event();
}; void affiche();
int button_map[10];
int axe_map[8];
private:
#else // !win32 => linux/apple int axe_min[8];
int axe_max[8];
int gamepad_fd;
#include <linux/joystick.h> char name[256];
#include <fcntl.h>
#if defined(WIN32)
#define GAMEPAD_DEV "/dev/input/js0"
JOYCAPS caps;
class GamePad { JOYINFOEX infoex;
public: JOYINFO info;
bool active; int axes;
bool toggle_status[GP_BUTTONS]; int buttons;
bool event_read;
double frequency; #else
GamePad(); #if defined(__APPLE__)
~GamePad();
double axe[GP_AXES]; // ??
bool button[GP_BUTTONS];
bool toggle(const int _nbut); #else // LINUX
int read_event();
void affiche(); js_event event;
int button_map[10]; __u32 version;
int axe_map[8]; __u8 axes;
__u8 buttons;
private: #endif
// time_t rawtime; #endif
int gamepad_fd; };
js_event event;
__u32 version;
__u8 axes;
__u8 buttons;
char name[256];
};
#endif //win32
#endif // _GAMEPAD_H_ #endif // _GAMEPAD_H_
...@@ -59,7 +59,7 @@ void Navigator::drawIcons() ...@@ -59,7 +59,7 @@ void Navigator::drawIcons()
glPushMatrix(); glPushMatrix();
glLineWidth( (float)CTX::instance()->lineWidth); glLineWidth( (float)CTX::instance()->lineWidth);
gl2psLineWidth((float)(CTX::instance()->lineWidth * gl2psLineWidth((float)(CTX::instance()->lineWidth *
CTX::instance()->print.epsLineWidthFactor)); CTX::instance()->print.epsLineWidthFactor));
glColor4ubv((GLubyte *) & CTX::instance()->color.smallAxes); glColor4ubv((GLubyte *) & CTX::instance()->color.smallAxes);
...@@ -601,6 +601,7 @@ void Navigator::drawIcons() ...@@ -601,6 +601,7 @@ void Navigator::drawIcons()
glDisable (GL_BLEND); glDisable (GL_BLEND);
glDisable (GL_LINE_SMOOTH);
glPopMatrix(); glPopMatrix();
} }
......
...@@ -43,7 +43,7 @@ static void gamepadWindow_handler(void *data) ...@@ -43,7 +43,7 @@ static void gamepadWindow_handler(void *data)
gamepadWindow* gmpd_win = (gamepadWindow*)data; gamepadWindow* gmpd_win = (gamepadWindow*)data;
GamePad* pad = &(CTX::instance()->gamepad); GamePad* pad = &(CTX::instance()->gamepad);
for (int i=0; i<std::min(13,GP_BUTTONS);i++) gmpd_win->gamepad.butt[i]->value(pad->button[i]); for (int i=0; i<std::min(13,GP_BUTTONS);i++) gmpd_win->gamepad.butt[i]->value(pad->button[i]);
for (int i=0; i<std::min(9,GP_AXES);i++) gmpd_win->gamepad.axe[i]->value(pad->axe[i]); for (int i=0; i<std::min(9,GP_AXES);i++) gmpd_win->gamepad.axe[i]->value( pad->axe[i] );
Fl::add_timeout(gmpd_win->frequency, gamepadWindow_handler,data); Fl::add_timeout(gmpd_win->frequency, gamepadWindow_handler,data);
gmpd_win->gamepad.mapping[16]->value(pad->axe_map[1]); gmpd_win->gamepad.mapping[16]->value(pad->axe_map[1]);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment