GLFW - glfwSetMousePos Bug on Mac OS X 10.7 with OpenGL camera - c++

I have been following the tutorials at http://opengl-tutorials.org and they are brilliant so far (I'm on a Mac so I am having to use OpenGL 3.2 and GLSL 1.50 rather than OpenGL 3.3 and GLSL 3.30). The only problem with the tutorials so far, is that with the 3D camera tutorial (Tutorial 6: Keyboard and Mouse), when I move my mouse, I do not get any rotation what so ever and if I do, it will only be slowly in the down direction; even if I move my mouse in any direction.
I have compiled the code given (OpenGL 2.1 and 3.x) as well as write it by hand, and this still presents this bug. I have not idea why this would happen. Could this be a bug with GLFW, Mac OS X or something else?

I know it's quite an old question, but I had the same issue so it might be of help. I have downloaded the code from the website and in common/controls.cpp this line was commented:
glfwSetMousePos(1024/2, 768/2);
Apparently there is a bug in GLFW with MacOS for which this instruction doesn't work properly. Hopefully they fixed it in the newer versions, but I haven't tested it yet.
On a side note, commenting this line will make the tutorial work, but you might experience some issues when clamping the vertical camera angle: if you move the mouse past the clamping point (say going up), the mouse position will keep updating and when you move the mouse down you will have to wait until it reaches the clamping point before the camera moves again.
[EDIT] Here's the full modified code
// Reset mouse position for next frame
// EDIT : Doesn't work on Mac OS, hence the code below is a bit different from the website's
//glfwSetMousePos(1024/2, 768/2);
// Compute new orientation
horizontalAngle = 3.14f + mouseSpeed * float( 1024/2 - xpos );
verticalAngle = mouseSpeed * float( 768/2 - ypos );

As GLFW3’s doc mention :
"The window must have input focus.”
So you should call glfwSetCursorPos until window have input focus ! It is not a bug in GLFW with MacOS !
The code should like that:
bool firstMouse = true;
float centerX = (float)mWidth / 2, centerY = (float)mHeight / 2;
GLFWwindow* mWindow;
void mouse_callback(GLFWwindow *window, double xPos, double yPos) {
if (firstMouse) {
// why here?
// As
// https://www.glfw.org/docs/3.3/group__input.html#ga04b03af936d906ca123c8f4ee08b39e7
// mention :
// "The window must have input focus."
glfwSetCursorPos(mWindow, centerX, centerY);
firstMouse = false;
}
// ...
}
void main() {
// ...
glfwSetCursorPosCallback(mWindow, mouse_callback);
// ...
}

There's still the same problem with GLFW 3 on OS X 10.9.
To disable the cursor and thus trap it inside the window I added this after the window is created.
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
Then I commented out //glfwSetCursorPos(window, 1024 / 2, 768 / 2); in controls.cpp
Now the mouse movement works. However, it seems like when viewing the cube from certain angle, the view is rotated when moving the mouse left and right while from other angle the view moves left and right as it should. Strange.

For GLFW2 on OSX add this line in your tutorial-XX.cpp after glfwCreateWindow( ...,...,)
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
and then create two global variables in common/controls.cpp
double xpos_old, ypos_old;
finally comment out the glfwSetCursorPos(window, 1024/2, 768/2); and change the calculation of the angles to the new setup, the idea is to get the difference between the old mousepos and the new. The final code should look like this:
// Reset mouse position for next frame
// glfwSetCursorPos(window, 1024/2, 768/2);
// Compute new orientation
horizontalAngle += mouseSpeed * float( xpos_old - xpos );
verticalAngle += mouseSpeed * float( ypos_old - ypos );
xpos_old = xpos;
ypos_old = epos;
This works great on my mac! cheers!

Related

GLFW-style infinite mouse movement in SDL2?

GLFW has a function which does exactly what I need:
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
This function lets the mouse to move freely without being bounded to the window or the screen.
One solution I found is to reset the mouse position each frame using:
SDL_WarpMouseInWindow(window, defaultMousePositionX, defaultMousePositionY);
But I would still like to know If there is something like glfwSetInputMode() in SDL2.
If you require relative movement, FPS style, SDL has a SDL_SetRelativeMouseMode function as seen here. This forces SDL to only report motion events, so the mouse position doesn't change.
Another method would be to track the current and next positions yourself and manually calculating the differential, to get the distance moved.
// Last position
lastX = currX;
lastY = currY;
// Current position
currX = event.motion.x;
currY = event.motion.y;
// Motion
motionX = currX - lastX;
motionY = currY - lastY;
This could translate smoothly to other control methods too, like analogue sticks and touch controls, giving you a more uniform experience should you decide to use other platforms.

OpenGL draw circle with Mouse Move

I am trying to use the function mouseMove(int x, int y) to draw a circle centered at my mouse as I click and drag it across the screen. Circles will be drawn on the moving mouse like a spray paint. So far, this is what I have
void mouseMove(int x, int y) {
glBegin(GL_POLYGON);
for (int i = 0; i <= 360; i++)
{
float theta = (2 * 3.14 * i) / 360;
glVertex2f((size/2 + x) * cos(theta), (size/2 + y) * sin(theta));
}
glEnd();
glutPostRedisplay();
}
But when using this, it draws very large circles that aren't centered around my mouse. How would I alter this to make the program draw circles centered at my mouse?
To describe the project, I am creating a painting program that changes shapes, colors, sizes, and rotations of the drawing done in mouseMove. For now, the size is an int set to 32. When the user selects the shape using the 'b' key in a keyboard function, he/she can switch the shapes that are drawn around the mouse as the user clicks and drags the mouse around. Like a spray paint. All the other shapes work shaped around the mouse except for the circle shape spray.
This answer assumes that things like your viewport and projection matrices are set up correctly, and that the input to this function is taking into account the fact that "screen coordinates" (what the mouse uses) are not the same thing as "OpenGL Coordinate Space" (this usually implies reversing the direction of the y-axis for one or the other).
The math you're using for setting your vertex coordinates is wrong. The mouse's x and y coordinates should not be multiplied by the sine/cosine functions.
The correct way to write it is
glVertex2f((size/2) * cos(theta) + x, (size/2) * sin(theta) + y);
I would also add that you appear to still be using OpenGL's Immediate Mode rendering, which is Deprecated and will offer extremely poor training for a professional setting. I highly advise you learn Modern OpenGL (3.x+) and reapply those concepts to whatever projects you're already working on. This is a very good tutorial.

Window resizing and scaling images / Redeclaring back buffer size / C++ / DIRECTX 9.0

C++ / Windows 8 / Win api / DirectX 9.0
I am having real big issues with this:
https://github.com/jimmyt1988/TheGame/tree/master/TheGame
Problem is that I have defined some adjust coordinate functions. They are for when a window is resized and I need to offset all of my coordinates so that my mouse cooridnates are working out the correct collisions and also to scale and yet keep ratio locked for the images I am drawing to the screen.
For example, If I had a screen at 1920 x 1080 and then resized to 1376 x 768, I need to make sure that the bounding boxes for my objects (for when my mouse hovers over them) is adjusted on the mouse coordinates I use to use to check if the mouse was in the bounding box.
I found out that I originally had problems because when I resized my window, directX was automatically scaling everything.. and on top of that, I too was rescaling things, so they would get utterly screwed... I was told by someone that I need to re-declare my screen buffer width and height, which I have done keeping in mind there is a border to my window and also a menu at the top.
Can anyone see why... regardless of doing all this stuff, I am still getting the incorrect results.
If you manage to run my application: Pressing the 1 key will make the resolution 1920 x 1080, pressing the 2 key will make it 1376 x 768. The resize is entirely wrong: https://github.com/jimmyt1988/TheGame/blob/master/TheGame/D3DGraphics.cpp
float D3DGraphics::ResizeByPercentageChangeX( float point )
{
float lastScreenWidth = screen.GetOldWindowWidth();
float currentScreenWidth = screen.GetWindowWidth();
if( lastScreenWidth > currentScreenWidth + screen.GetWidthOffsetOfBorder() )
{
float percentageMoved = currentScreenWidth / lastScreenWidth;
point = point * percentageMoved;
}
return point;
}
float D3DGraphics::ResizeByPercentageChangeY( float point )
{
float lastScreenHeight = screen.GetOldWindowHeight();
float currentScreenHeight = screen.GetWindowHeight();
if( lastScreenHeight > currentScreenHeight + screen.GetHeightOffsetOfBorderAndMenu() )
{
float percentageMoved = currentScreenHeight / lastScreenHeight;
point = point * percentageMoved;
}
return point;
}
and yet if you put the return point above this block of code and just do nothing to it, it scales perfectly because of blooming directX regardless of this which is being called correctly (presparams are previously declared in the D3DGraphics construct and a reference held in the class its self:
void D3DGraphics::ResizeSequence()
{
presParams.BackBufferWidth = screen.GetWindowWidth() - screen.GetWidthOffsetOfBorder();
presParams.BackBufferHeight = screen.GetWindowHeight() - screen.GetHeightOffsetOfBorderAndMenu();
d3dDevice->Reset( &presParams );
}
This is the problem at hand:
Here is the code that makes this abomination of a rectangle:
void Game::ComposeFrame()
{
gfx.DrawRectangle( 50, 50, screen.GetWindowWidth() - screen.GetWidthOffsetOfBorder() - 100, screen.GetWindowHeight() - screen.GetHeightOffsetOfBorderAndMenu() - 100, 255, 0, 0 );
}
EDIT::::::::::::::::
I noticed that On MSDN it says:
Before calling the IDirect3DDevice9::Reset method for a device, an
application should release any explicit render targets, depth stencil
surfaces, additional swap chains, state blocks, and D3DPOOL_DEFAULT
resources associated with the device.
I have now released the vbuffer and reinstantiated it after the presparams and device are reset.
EDIT::::::::::::
I placed an HRESULT on my reset in which I now manage to trigger an error... But, well.. it doesn't really help me! : http://i.stack.imgur.com/lqQ5K.jpg
Basically, the issue was I was being a complete derp. I was putting into my rectangle the window width and then readjusting that size based on the oldwidth / newwidth.. well the new width was already the screen size... GRRRRRRR.

Preserving rotations in OpenGL

I'm drawing an object (say, a cube) in OpenGL that a user can rotate by clicking / dragging the mouse across the window. The cube is drawn like so:
void CubeDrawingArea::redraw()
{
Glib::RefPtr gl_drawable = get_gl_drawable();
gl_drawable->gl_begin(get_gl_context());
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
{
glRotated(m_angle, m_rotAxis.x, m_rotAxis.y, m_rotAxis.z);
glCallList(m_cubeID);
}
glPopMatrix();
gl_drawable->swap_buffers();
gl_drawable->gl_end();
}
and rotated with this function:
bool CubeDrawingArea::on_motion_notify_event(GdkEventMotion* motion)
{
if (!m_leftButtonDown)
return true;
_3V cur_pos;
get_trackball_point((int) motion->x, (int) motion->y, cur_pos);
const double dx = cur_pos.x - m_lastTrackPoint.x;
const double dy = cur_pos.y - m_lastTrackPoint.y;
const double dz = cur_pos.z - m_lastTrackPoint.z;
if (dx || dy || dz)
{
// Update angle, axis of rotation, and redraw
m_angle = 90.0 * sqrt((dx * dx) + (dy * dy) + (dz * dz));
// Axis of rotation comes from cross product of last / cur vectors
m_rotAxis.x = (m_lastTrackPoint.y * cur_pos.z) - (m_lastTrackPoint.z * cur_pos.y);
m_rotAxis.y = (m_lastTrackPoint.z * cur_pos.x) - (m_lastTrackPoint.x * cur_pos.z);
m_rotAxis.z = (m_lastTrackPoint.x * cur_pos.y) - (m_lastTrackPoint.y * cur_pos.x);
redraw();
}
return true;
}
There is some GTK+ stuff in there, but it should be pretty obvious what it's for. The get_trackball_point() function projects the window coordinates X Y onto a hemisphere (the virtual "trackball") that is used as a reference point for rotating the object. Anyway, this more or less works, but after I'm done rotating, and I go to rotate again, the cube snaps back to the original position, obviously, since m_angle will be reset back to near 0 the next time I rotate. Is there anyway to avoid this and preserve the rotation?
Yeah, I ran into this problem too.
What you need to do is keep a rotation matrix around that "accumulates" the current state of rotation, and use it in addition to the rotation matrix that comes from the current dragging operation.
Say you have two matrices, lastRotMx and currRotMx. Make them members of CubeDrawingArea if you like.
You haven't shown us this, but I assume that m_lastTrackPoint is initialized whenever the mouse button goes down for dragging. When that happens, copy currRotMx into lastRotMx.
Then in on_motion_notify_event(), after you calculate m_rotAxis and m_angle, create a new rotation matrix draggingRotMx based on m_rotAxis and m_angle; then multiply lastRotMx by draggingRotMx and put the result in currRotMx.
Finally, in redraw(), instead of
glRotated(m_angle, m_rotAxis.x, m_rotAxis.y, m_rotAxis.z);
rotate by currRotMx.
Update: Or instead of all that... I haven't tested this, but I think it would work:
Make cur_pos a class member so it stays around, but it's initialized to zero, as is m_lastTrackPoint.
Then, whenever a new drag motion is started, before you initialize m_lastTrackPoint, let _3V dpos = cur_pos - m_lastTrackPoint (pseudocode).
Finally, when you do initialize m_lastTrackPoint based on the mouse event coords, subtract dpos from it.
That way, your cur_pos will already be offset from m_lastTrackPoint by an amount based on the accumulation of offsets from past arcball drags.
Probably error would accumulate as well, but it should be gradual enough so as not to be noticeable. But I'd want to test it to be sure... composed rotations are tricky enough that I don't trust them without seeing them.
P.S. your username is demotivating. Suggest picking another one.
P.P.S. For those who come later searching for answers to this question, the keywords to search on are "arcball rotation". An definitive article is Ken Shoemake's section in Graphical Gems IV. See also this arcball tutorial for JOGL.

Trapping the mouse?

I'm using GLUT and developing a FPS game. I need a way to trap the mouse so that the camera continues to move because right now when the mouse position exceeds the monitor limit, there is no way to calculate change in X or change in Y. How can I 'trap' the mouse with GLUT?
Thanks
I'd recommend using a ready-made engine like OGRE 3D instead, but if you really want to reinvent the wheel, here's how...
In all cases I'm aware of, PC FPS games "trap" the pointer by registering a mouse motion callback, noting the relative motion, and then warping the pointer back to the center of the window.
Here's some code I wrote to add mouse input to a sample ping-pong table in an OpenGL with C++ course a year or two ago:
void resetPointer() {
glutWarpPointer(TABLE_X/2, TABLE_Y/2);
lastMousePos = TABLE_Y/2;
}
void mouseFunc(int sx, int sy) {
if (!started) { return; }
int vertMotion = lastMousePos - sy;
lastMousePos = sy;
player1.move(vertMotion);
// Keep the pointer from leaving the window.
if (fabs(TABLE_X/2 - sx) > 25 || fabs(TABLE_Y/2 - sy) > 25) {
resetPointer();
}
}
// This goes in with your "start new game" code if you want a menu
resetPointer();
glutSetCursor(GLUT_CURSOR_NONE);
glutPassiveMotionFunc(mouseFunc);
It only tracks vertical motion, but adding horizontal is trivial.