Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Bug in Window/Win32/JoystickImpl.cpp  (Read 4256 times)

0 Members and 1 Guest are viewing this topic.

CopyConstructor

  • Newbie
  • *
  • Posts: 6
    • View Profile
Bug in Window/Win32/JoystickImpl.cpp
« on: February 24, 2016, 09:09:08 pm »
Hi,

For me, querying the axis position of the POV is buggy under windows:
 ( Joystick::getAxisPosition(0,Joystick::Axis::PovX) )  it returns strange values.

The reason is located in Window/Win32/JoystickImpl.cpp:

JoystickState JoystickImpl::update()
{
    JOYINFOEX pos;
    pos.dwFlags  = JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | JOY_RETURNBUTTONS;
    pos.dwFlags |= (m_caps.wCaps & JOYCAPS_POVCTS) ? JOY_RETURNPOVCTS : JOY_RETURNPOV;
    pos.dwSize   = sizeof(JOYINFOEX);
    if (joyGetPosEx(m_index, &pos) == JOYERR_NOERROR)
    {
....    
       // Special case for POV, it is given as an angle
        if (pos.dwPOV != 0xFFFF)
        {
            float angle = pos.dwPOV / 18000.f * 3.141592654f;  //Bug: angle is in *degrees*!
            state.axes[Joystick::PovX] = std::sin(angle) * 100;
            state.axes[Joystick::PovY] = std::cos(angle) * 100;
        }
        else
        {
            state.axes[Joystick::PovX] = 0;
            state.axes[Joystick::PovY] = 0;
        }
  }
...
}
 

The error is pos.dwPOV is in degrees already! (*100)
For me, this degrees either with Flag JOYCAPS_POVCTS or JOY_RETURNPOVCTS.
Only the convertion for range [-100 .. 100] is needed.
( But I would really recommend to use a angle (radiants or degrees) for the POV, all other is not intuitive. )

According to MSDN this is right:

dwPOV
Current position of the point-of-view control. Values for this member are in the range 0 through 35,900. These values represent the angle, in degrees, of each view multiplied by 100.
JOY_RETURNPOV   
The dwPOV member contains valid information about the point-of-view control, expressed in discrete units.
JOY_RETURNPOVCTS   
The dwPOV member contains valid information about the point-of-view control expressed in continuous, one-hundredth degree units.

https://msdn.microsoft.com/de-de/library/windows/desktop/dd757112.aspx

My Situation:
Joystick is: Speedlink Phantom Hawk
Driver: default windows 10 driver (nothing additional installed from manufacturer)
OS: Windows 10


Workaround:
Use joyGetPosEx() by your own:
                               
#include <Mmsystem.h>

        JOYINFOEX pos;
        pos.dwFlags = JOY_RETURNPOVCTS;// or  JOY_RETURNPOV give the same: degrees for my stick
        pos.dwSize = sizeof(JOYINFOEX);
        if (joyGetPosEx(JOYSTICK_1, &pos) == JOYERR_NOERROR)
        {
                if (pos.dwPOV != JOY_POV_CENTERED)
                { // use pos.dwPOV
                }
        }
.....

This values are correct for my joystick:
#define JOY_POV_CENTERED                (WORD) -1
#define JOY_POV_FORWARD                 JOY_POVFORWARD
#define JOY_POV_RIGHT_FORWARD   4500
#define JOY_POV_RIGHT                   JOY_POVRIGHT
#define JOY_POV_RIGHT_BACKWARD  13500
#define JOY_POV_BACKWARD                JOY_POVBACKWARD
#define JOY_POV_LEFT_BACKWARD   22500
#define JOY_POV_LEFT                    JOY_POVLEFT
#define JOY_POV_LEFT_FORWARD    31500
 

 
This bug was already noticed 4 Years ago!
Why the hack is this not corrected?

http://fr.sfml-dev.org/forums/index.php?topic=7054.0


« Last Edit: February 24, 2016, 09:12:05 pm by CopyConstructor »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #1 on: February 25, 2016, 08:36:20 am »
Quote
The error is pos.dwPOV is in degrees already! (*100)
Yes... and that's why we convert it to radians, in order to decompose the angle into separate X and Y values.

So, instead of writing a wall of text about what you think is the problem and its solution (and which is plain wrong -- unless I misunderstood what you said), why don't you just explain your problem? ;)
Laurent Gomila - SFML developer

CopyConstructor

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #2 on: February 25, 2016, 10:35:46 am »
The "Bug" comment ist misplaced, sorry for that.

For example, I get the following values:

POV to the right:   
povX = 100                       
povY = -4.37113886e-06 

POV to Backwards:
povX = -8.74227771e-06 
povY = -100

how do this values fit to radiants?

And why does is the documentation for:

Joystick::getAxisPosition only say: "Current position of the axis, in range [-100 .. 100] "?
at least for for POV this is not very helpful.
   
I thought I would help you to quick fix this issue, so I made the work and wrote all I knew about it .
Sorry for that - I will never try to help again.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #3 on: February 25, 2016, 10:51:58 am »
Like I said, SFML doesn't give you the POV in radians, but its decomposed X and Y axes in [-100 .. 100], like all other axes. So the values that you get are perfectly fine.

Quote
I thought I would help you to quick fix this issue, so I made the work and wrote all I knew about it .
Sorry for that - I will never try to help again.
And that's really appreciated. But you wasted your efforts in a wrong direction, where your problem was just about properly understanding the API. That's a very common "issue".
Laurent Gomila - SFML developer

CopyConstructor

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #4 on: February 25, 2016, 11:43:27 am »
Ok, than: it's a strange design (not to say "bug")

Sorry.. it really makes no sense to set the other angle to a value like -4.37113886e-06
and not reflect it to the documentation.
How do I get the 4 other (diagonal) POV directions? ( upper left, lower right ...)

I will continue to use Microsoft's joyGetPosEx() API and recommend that for other confused users. The original API is much more clear and better documented.
With this implementation of querying the current POV direction, you don't reach your own Philosophy for a Simple easy to use API.
« Last Edit: February 25, 2016, 11:48:09 am by CopyConstructor »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #5 on: February 25, 2016, 01:13:25 pm »
Being so angry is not going to help. But anyway, I'll try to answer as best as I can.

Quote
Sorry.. it really makes no sense to set the other angle to a value like -4.37113886e-06
and not reflect it to the documentation.
This value is zero (-4e-6 is 0.000004), with the inaccuracy of the analog stick and/or floating point numbers.
The documentation states that PovX and PovY are axes, so they behave like all other "regular" axes (like X and Y of your directional pad), really. There's nothing special about them.

Quote
How do I get the 4 other (diagonal) POV directions? ( upper left, lower right ...)
Upper left is X=100 and Y=100, lower right is X=-100 and Y=-100, etc.

Quote
I will continue to use Microsoft's joyGetPosEx() API and recommend that for other confused users. The original API is much more clear and better documented.
With this implementation of querying the current POV direction, you don't reach your own Philosophy for a Simple easy to use API.
It's clearly documented and easy to understand, it's just not what you had in mind after your experience with the Win32 API. If you had read the thread you linked above, you'd have seen that it's just Windows that treats POV as an angle, Linux for example directly decomposes it as X and Y, like SFML does.

And if you really need an angle it's just a call to std::atan2(y, x) anyway.
Laurent Gomila - SFML developer

CopyConstructor

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #6 on: February 25, 2016, 02:17:37 pm »
Quote
This value is zero (-4e-6 is 0.000004), with the inaccuracy of the analog stick and/or floating point numbers.

Ok, I see this value should be zero.
But  that's the Problem! The POV is digital (at least my one).

If a consumer want's to deal with POV (direction) pressed/not pressed, he has to deal with floating point    inaccuracy. It's slower and not very intuitive (with digital buttons).

And, above all, the windows API returns accurate values. Why not use them in a switch statement and return accurate values too instead of dealing with sin/cos  and floating point inaccuracy?
Or the other way: Are there Joysticks, where the POV is analog? I have 4 different joysticks here, from cheap to expensive and none of them have analog POV axis.

Quote
If you had read the thread you linked above, you'd have seen that it's just Windows that treats POV as an angle, Linux for example directly decomposes it as X and Y, like SFML does

Have you ever thought about that the Linux implementation can be done better?

I think this is a common issue about: http://www.connexin.net/computer-software-humor-jokes/what-programmers-say.png



« Last Edit: February 25, 2016, 02:35:35 pm by CopyConstructor »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #7 on: February 25, 2016, 03:08:16 pm »
Instead of arguing here, you should rather retry what you were doing before coming on this forum, and you'll see that there really is no problem about this.

Quote
floating point    inaccuracy
Use a dead zone / thresholds.

Quote
the windows API returns accurate values
std::round(std::atan2(y, x) * 18000 / pi).

Quote
Have you ever thought about that the Linux implementation can be done better?
That was just to show that someone coming from a different environment might have other expectations than a Win32 user. Whether one or the other is "better" is mostly a matter of taste, because these are just two ways of showing the same data, and only one line of code is required to convert between each representation, if you really need to.
« Last Edit: February 25, 2016, 03:10:09 pm by Laurent »
Laurent Gomila - SFML developer

CopyConstructor

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #8 on: February 25, 2016, 06:53:19 pm »
I know it's hard to accept when "your babe" is criticized from a unknown person.  I understand your point of view.

And I Agree, it is not a bug:  but it's neither a feature.

You don't answered my two concrete questions:

Quote
Are there Joysticks, where the POV is analog?
Quote
Why not use them in a switch statement and return accurate values too instead of dealing with sin/cos  and floating point inaccuracy?
« Last Edit: February 25, 2016, 06:56:02 pm by CopyConstructor »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #9 on: February 25, 2016, 08:36:11 pm »
Quote
I know it's hard to accept when "your babe" is criticized from a unknown person.
Nothing to do with that. Actually I (and the other members of the team as well) love when someone raises a valid concern and starts a useful discussion about the API. This is what helps to make it better and better. But in your case, all I see is that you prefer to deal with POV as an angle rather than two separate axes. To be honest, I think this whole discussion leads nowhere and really bothers me, but I'll keep on replying as best as I can until you're satisfied ;)

Quote
Are there Joysticks, where the POV is analog?
I don't know how joysticks are made. I'm not a gamer, I'm not sure I even used a POV once in my life. I don't see where this question brings us.

Quote
Why not use them in a switch statement and return accurate values too instead of dealing with sin/cos  and floating point inaccuracy?
As already said 3 times: SFML decomposes the angle. If you want the angle back, call std::atan2. Not a big deal. Windows doesn't return accurate values, it just rounds the angle to 2 decimals. Which you can also do yourself, if you really want to.
« Last Edit: February 25, 2016, 08:37:51 pm by Laurent »
Laurent Gomila - SFML developer

CopyConstructor

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #10 on: February 26, 2016, 02:43:20 pm »
You misunderstood me.
I have no problem to use Joystick::Axis::PovX the way SFML implements it.

I am only wondering why the POV is implemented as Axis.
You are right, I don't know the Linux AP., I'm Windows Programmer from the first hour, so please be understanding: The only reason I see for using POV Buttons as Axis is, "because Linux does so".
Maybe in Linux APi the distinction between POV/non POV Axis is a problem?

Since the 1980's, I've seen really a lot of different Joysticks. All of them used
4 to 8 micro switches for the 4 - 8 different POV "directions" - if they had a POV control.

Many games are using these "directions" as simple buttons to "extend" the number of joystick buttons. In Hardware, they *are* switches ordered in in 4 or  8 "directions" -  On this background, implementing them as axis sounds strange to me.

Look at the Microsoft Windows API: There are already constants for the 4 main directions (joystickapi.h)
JOY_POVFORWARD
JOY_POVRIGHT
JOY_POVBACKWARD
JOY_POVLEFT

( The opposed: Seeing the POV as "normal" key's is also wrong, since they are ordered in directions and
normal joystick keys do not give a indication about their position. )
So: I still think the Microsoft approach is better.

Btw.: I'm also no Player (any more) (when I was young, I was).

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #11 on: February 26, 2016, 03:58:23 pm »
What I remembered from joystick POVs was more like a pair of axes, but if they are more like buttons, then yes it might be relevant to change the API.

Unfortunately I'm not the right person to talk about joysticks ;D so that's all I can say.
Laurent Gomila - SFML developer

Mario

  • SFML Team
  • Hero Member
  • *****
  • Posts: 879
    • View Profile
Re: Bug in Window/Win32/JoystickImpl.cpp
« Reply #12 on: February 27, 2016, 02:16:25 pm »
From my experience, (pretty much?) all POV switches/coolie hats are implemented either using 4 (cheaper) or 8 (more expensive/accurate) switches. I've never seen any POV that's indeed been some mini analog joystick (it's not really practical). XInput gamepads also implement their DPad as a coolie hat/POV with typically 4 switches.

Also note that at least Windows' default gamepad configuration (joy.cpl) is only able to display 8 fixed directions rather than a freeflow angle.

 

anything