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
No related branches found
No related tags found
No related merge requests found
......@@ -4,70 +4,6 @@
// bugs and problems to the public mailing list <gmsh@geuz.org>.
//
// Contributed by Gilles Marckmann <gilles.marckmann@ec-nantes.fr>
#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
//
// ###### ######
......@@ -76,7 +12,7 @@
// ............ .......... .
// ...#######... ...########..
// ..# but4 #... ...# but6 #..
// ...########....... but9 but10........#########..
// ...########....... ........#########..
// .................... .....................
// .......#................... ..........................
// ......axis5..........................................####.......
......@@ -94,7 +30,7 @@
// .....................## | ##..........## | ##.....................
// ......................#<--axis0-->#..........#<--axis2--> #.....................
// ......................## | ##. .####. .## | ##......................
// .......................## | ##.. # b8 #...## | ##.......................
// .......................## | ##.. # b9 #...## | ##.......................
// ..........................#######......####......#######.........................
// ..................................................................................
// ..................... .......... ......... .....................
......@@ -112,26 +48,118 @@
// .... ...
//
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;
#include <cstring>
#include <string>
#include <iostream>
#include <stdio.h>
#include "GamePad.h"
#include "Context.h"
#include <unistd.h>
// other recognized map "Thrustmaster Run'N' Drive Wireless PS3"
#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() {
if (gamepad_fd > 0) { active = false; close(gamepad_fd); }
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;}
......@@ -139,59 +167,112 @@
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)
{
// time( &rawtime );
switch (event.type)
{
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:
// 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; }
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;
#endif //(__APPLE__)
#endif //(WIN32)
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
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;
}
......@@ -14,8 +14,18 @@
#define GP_AXES 6
#if defined(WIN32) || defined(__APPLE__)
#if defined(WIN32)
#include <windows.h>
#include <mmsystem.h>
#else
#if defined(__APPLE__)
// ??
#else // LINUX
#include <linux/joystick.h>
#include <fcntl.h>
#define GAMEPAD_DEV "/dev/input/js0"
#endif
#endif
class GamePad {
public:
......@@ -33,51 +43,33 @@
int button_map[10];
int axe_map[8];
private:
int axe_min[8];
int axe_max[8];
int gamepad_fd;
// js_event event;
// __u32 version;
// __u8 axes;
// __u8 buttons;
char name[256];
};
#if defined(WIN32)
#else // !win32 => linux/apple
JOYCAPS caps;
JOYINFOEX infoex;
JOYINFO info;
int axes;
int buttons;
#else
#if defined(__APPLE__)
#include <linux/joystick.h>
#include <fcntl.h>
// ??
#define GAMEPAD_DEV "/dev/input/js0"
#else // LINUX
class GamePad {
public:
bool active;
bool toggle_status[GP_BUTTONS];
bool event_read;
double frequency;
GamePad();
~GamePad();
double axe[GP_AXES];
bool button[GP_BUTTONS];
bool toggle(const int _nbut);
int read_event();
void affiche();
int button_map[10];
int axe_map[8];
private:
// time_t rawtime;
int gamepad_fd;
js_event event;
__u32 version;
__u8 axes;
__u8 buttons;
char name[256];
};
#endif //win32
#endif
#endif
};
#endif // _GAMEPAD_H_
......@@ -601,6 +601,7 @@ void Navigator::drawIcons()
glDisable (GL_BLEND);
glDisable (GL_LINE_SMOOTH);
glPopMatrix();
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment