Jump to content
  • Advertisement
mister345

C++ Bit manipulation returning wrong data

Recommended Posts

Hi, I'm trying to return two 32 bit int values (_mouseX and _mouseY) from a function by packing them into a 64 bit value first, then unpacking them elsewhere in the code when I use them. However, the data is completely incorrect when I get it through this function. I already confirmed that the original _mouseX and _mouseY data and the SetOrientation functions are fine; the problem is somewhere in the bitshifting or maybe casting or teh types Im using in this GetMouseXY function. Could you please have a look? Thanks.

    long int Input::GetMouseXY()
    {
        return (_mouseX << 32) |_mouseY;
    }
    
    long int mouseY = pInput->GetMouseXY() & 0xFFFFFFFF;
    long int mouseX = (pInput->GetMouseXY() >> 32) & 0xFFFFFFFF;
    _CamPosition->SetOrientation(XMFLOAT3((float)mouseY, (float)mouseX, 0.f));

Share this post


Link to post
Share on other sites
Advertisement

Are the original _mouseX and _mouseY int's? They should be casted to 64-bit numbers before you are able to correctly shift them 32 bits.

Share this post


Link to post
Share on other sites
32 minutes ago, DaBono said:

Are the original _mouseX and _mouseY int's? They should be casted to 64-bit numbers before you are able to correctly shift them 32 bits.

I tried casting them and the data is still wrong.

 

long int Input::GetMouseXY()
{
    return ((long int)_mouseX << 32) | (long int)_mouseY;
}
 

Share this post


Link to post
Share on other sites

The mouse (in Windows) is given as a 16 bit signed value, so just use <<16, >>16, and 0xFFFF.

Also, a long int is a 32 bit value, not 64.

Share this post


Link to post
Share on other sites
15 minutes ago, mister345 said:

I tried casting them and the data is still wrong.

 

long int Input::GetMouseXY()
{
    return ((long int)_mouseX << 32) | (long int)_mouseY;
}
 

I believe "long int" is still 32bits in Windows. Try using "long long" or (u)int64_t

Share this post


Link to post
Share on other sites
22 minutes ago, Mk_ said:

The mouse (in Windows) is given as a 16 bit signed value, so just use <<16, >>16, and 0xFFFF.

Also, a long int is a 32 bit value, not 64.

tried your theory about 16 bits but still doesnt work. Should it be an unsigned int or not? Couldnt the mouse x or y values be negative? Also, if it should be an unsigned int, maybe it needs to be stored inside a 64 int anyway bc a 32 bit int could get messed up by the sign bit? Just guessing now.

int Input::GetMouseXY()
{
    return (_mouseX << 16) | _mouseY;
}

    int mouseY = pInput->GetMouseXY() & 0xFFFF;
    int mouseX = (pInput->GetMouseXY() >> 16) & 0xFFFF;
    _CamPosition->SetOrientation(XMFLOAT3((float)mouseY, (float)mouseX, 0.f));

 

Share this post


Link to post
Share on other sites

Check the definition of _mouseX & Y. Windows desktop uses SIGNED 16 bit values for the mouse, but maybe they're being converted to int by whatever library you're using. If you go the 64bit router use __int64.

Share this post


Link to post
Share on other sites

It's not clear how you get mouse input, but if you use the windows mouse messages (WM_MOUSEMOVE, etc) then the values received there are (signed) 16bit as Mk_ stated.

If bit manipulation is giving you trouble, then you can use unions as an alternative.

Share this post


Link to post
Share on other sites
2 hours ago, mister345 said:

long int Input::GetMouseXY()
    {
        return (_mouseX << 32) |_mouseY;
    }

As others have stated, that is probably not a 64bit result and you are loosing the x position, change the code as follows to guarantee things:

int64_t Input::GetMouseXY()
    {
        return (int64_t(_mouseX) << 32) | int64_t(_mouseY);
    }

Alternatively, and more difficult to get wrong or mess up later, use a combination of a union and bit fields:

union MousePosition
{
  int64_t Data;
  struct
  {
    int32_t X : 32;
    int32_t Y : 32;
  } Position;
};

Then you can:

int64_t Input::GetMouseXY()
    {
       MousePosition result;
       result.Position.X = _mouseX;
       result.Position.Y = _mouseY;
       return result.Data;
    }

The bit field makes the code more verbose but also more understandable.  It will do the magic of bit shifting and compositing the result for you automatically in a safe manner.  (Note that in the above case, if you really want 32 bit values, you don't need the bitfield, I put it in there since I usually pack more data into that structure.)  Unpacking the data is the following:

MousePosition pos;
pos.Data = theInt64ReturnedAbove;
int32_t x = pos.Position.X;
int32_t y = pos.Position.Y;

 

Share this post


Link to post
Share on other sites
43 minutes ago, All8Up said:

As others have stated, that is probably not a 64bit result and you are loosing the x position, change the code as follows to guarantee things:

int64_t Input::GetMouseXY()
    {
        return (int64_t(_mouseX) << 32) | int64_t(_mouseY);
    }

Alternatively, and more difficult to get wrong or mess up later, use a combination of a union and bit fields:

union MousePosition
{
  int64_t Data;
  struct
  {
    int32_t X : 32;
    int32_t Y : 32;
  } Position;
};

Then you can:

int64_t Input::GetMouseXY()
    {
       MousePosition result;
       result.Position.X = _mouseX;
       result.Position.Y = _mouseY;
       return result.Data;
    }

The bit field makes the code more verbose but also more understandable.  It will do the magic of bit shifting and compositing the result for you automatically in a safe manner.  (Note that in the above case, if you really want 32 bit values, you don't need the bitfield, I put it in there since I usually pack more data into that structure.)  Unpacking the data is the following:

MousePosition pos;
pos.Data = theInt64ReturnedAbove;
int32_t x = pos.Position.X;
int32_t y = pos.Position.Y;

 

Very interesting. I tried your way of using int64_t

__int64 Input::GetMouseXY()
{
    return (__int64(_mouseX) << 32) | __int64(_mouseY);
}

    __int64 mouseXY = pInput->GetMouseXY();
    __int64 mouseY = mouseXY & 0xFFFFFFFF;
    __int64 mouseX = (mouseXY >> 32) & 0xFFFFFFFF;
    _CamPosition->SetOrientation(XMFLOAT3((float)mouseY, (float)mouseX, 0.f));

and both x and y rotation start out locked at a 10 digit number around -2100000000, but if you keep looking downwards and do a "somersault" with the mouse so you end up with a pitch of over 360, then do the same "winding up over 360" with the yaw, then suddenly the mouse look works perfectly for both x and y. So for some reason this implementation makes values between 0 and 360 invalid. (Notice I also had to reverse X and Y when passing them into SetOrientation().

Absolutely bizarre. Anyway, the code is here if anyone's curious.

https://github.com/mister51213/DirectX11Engine/blob/Restructure/DirectX11Engine/Input.cpp

https://github.com/mister51213/DirectX11Engine/blob/Restructure/DirectX11Engine/World.cpp

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!