Handmade Hero » Forums » Game » Transformation of the mouse coordinates (day 188+)
r2d2
31 posts
#13008 Transformation of the mouse coordinates (day 188+)
2 months, 2 weeks ago Edited by on Sept. 4, 2017, 2:11 p.m.

Hello, everyone.

In day 188 Casey adds support for mouse hover. He retrieves the current mouse cursor position and transforms it into the game's coordinate space:

1
2
3
4
5
POINT MouseP;
GetCursorPos(&MouseP);
ScreenToClient(Window, &MouseP);
NewInput->MouseX = (-0.5f*(r32)GlobalBackbuffer.Width + 0.5f) + (r32)MouseP.x;
NewInput->MouseY = (0.5f*(r32)GlobalBackbuffer.Height - 0.5f) - (r32)MouseP.y;


GlobalBackbuffer.Width and GlobalBackbuffer.Height should be set, apparently, to 1920 and 1080, respectively. I am trying to achieve the same effect in my Mac OS X build like this:

1
2
3
4
NSPoint MousePos = [Window mouseLocationOutsideOfEventStream];

Input.MouseX = (-0.5f * (r32) Framebuffer.Width + 0.5f) + (r32) MousePos.x;
Input.MouseY = (-0.5f * (r32) Framebuffer.Height + 0.5f) + (r32) MousePos.y;


The Y differs because Mac OS X doesn't do Y in top-to-bottom unlike Windows. The framebuffer is set to 1440x900 in the code (I'm on 15" retina screen). It works OK when my game is fullscreen. However, if it is not or if the window is resized to a smaller size, my mouse goes off. The hover effect occurs when the cursor is not above the debug bars but somewhere outside.

Obviously this is because the X and Y are transformed based on 1440x900 but the actual window size is smaller. What I don't get is why the Windows build, judging from the videos, does not suffer the same problem? No matter what the game window's size is, the cursor behaves OK and the hover check (it's a IsInRectange call) passes when the cursor strictly above the graph bar. Could somebody give me a hint? I've been staring at the windows code for some time now and playing around with the debugger on my own version but have no clue so far how to fix this.
mrmixer
Simon Anciaux
283 posts
#13026 Transformation of the mouse coordinates (day 188+)
2 months, 2 weeks ago

I don't know what the problem is, here are some ideas:
- The position of the mouse may be in screen space instead of being relative to your application window (the client area is the windows size minus the borders. ScreenToClient, I don't know what [Window mouseLocationOutsideOfEventStream] gives).
- If you resize the window you probably want to resize the backbuffer, or at least use the dimensions of the new window size instead of GlobalBackbuffer.Width/Height.
- Step in the code to see if each values are what you expect (compute them by hand).
- You can try to put your mouse at precise spots (e.g. the corner of your window, near the center...) and print the position or use the debugger to see if they matches what you expect.
- You can try to draw something at MouseP to see if it follows the cursor.
r2d2
31 posts
#13027 Transformation of the mouse coordinates (day 188+)
2 months, 2 weeks ago

Hi, Simon!

Thanks for the suggestions.

> - The position of the mouse may be in screen space instead of being relative to your application window (the client area is the windows size minus the borders. ScreenToClient, I don't know what [Window mouseLocationOutsideOfEventStream] gives).
It returns exactly the position of the mouse in window space, I've checked: (0, 0) starts at bottom-left corner of the window.

> - If you resize the window you probably want to resize the backbuffer, or at least use the dimensions of the new window size instead of GlobalBackbuffer.Width/Height.
Already tried that. I pass the actual window size (the content area) to the transformation code. I also tried to offset the mouse coordinates as suggested here, but it doesn't help. I've started thinking in the same direction that maybe I should consider resizing the backbuffer, maybe the mouse position is off because of that.

> - You can try to put your mouse at precise spots (e.g. the corner of your window, near the center...) and print the position or use the debugger to see if they matches what you expect.
Yes, did that too, it reports proper values for mouse positions in screen space (i.e. when not transformed).

> - You can try to draw something at MouseP to see if it follows the cursor.
There's already a small text that shows up when you hover over the debug bars that shows which line and which function are denoted by that particular bar.

That's why I'm thinking that the mouse position is calculated properly and I need to dig into how the coordinates of the bars themselves are calculated. I'll keep digging in that direction.
r2d2
31 posts
#13028 Transformation of the mouse coordinates (day 188+)
2 months, 2 weeks ago

Hmmph. Maybe I was doing something wrong yesterday but today the following code works properly:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
NSPoint MousePos = [Window mouseLocationOutsideOfEventStream];
NSRect ContentRect = [Window contentRectForFrameRect: [Window frame]];

r32 OffsetX = (r32) Framebuffer.Width / (r32) ContentRect.size.width;
r32 OffsetY = (r32) Framebuffer.Height / (r32) ContentRect.size.height;

Input.MouseX = (-0.5f * (r32) ContentRect.size.width + 0.5f) + (r32) MousePos.x;
Input.MouseY = (-0.5f * (r32) ContentRect.size.height + 0.5f) + (r32) MousePos.y;

Input.MouseX *= OffsetX;
Input.MouseY *= OffsetY;


I get a correct transformation no matter whatever my game window size is and wherever it is located on the screen. This still doesn't explain though, why no such adjustment is being made in the original code.
mrmixer
Simon Anciaux
283 posts
#13031 Transformation of the mouse coordinates (day 188+)
2 months, 2 weeks ago

I just thought that the aspect ratio of your screen is 16/10 while Casey's is 16/9.
If at some place in the code the aspect ratio is computed to be 16/9 that could explain the difference.