Interaction with Mouse in OpenGL (Part 2)

Print Friendly, PDF & Email

In fact, transformations are relative to the object. You need to keep track of your transforms and move things as appropriate for the current state of the model view matrix. Everything is relative, so it doesn’t really make sense to talk about absolute position in this way. You can try glPushMatrix(), glLoadIdentity(), glTranslatef(0.1f0, 0.2f0, 0.0f0), draw-gl-scene, and glPopMatrix(), which may or may not be what you actually want to do.

Moving selected objects in OpenGL
What you need to do is check whenever the mouse is moved AND if the player is holding the button you use to move objects. You also need to check if the user has already clicked on an object to move and is then holding the mouse to move it.

Here’s the steps:
1. User mouse clicks down on object
2. Call function with mouse down
3. User keeps mouse held down and moves mouse
4. Call function with mouse motion
5. User stops holding mouse down
6. Call function with mouse up

void reshape(int w, int h) {
glViewport(0, 0, (GLint) w, (GLint) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if ( h==0 )
gluPerspective(45, (GLdouble)w, 1.0, 2000.0);
else
gluPerspective(45, (GLdouble)w/ (GLdouble)h, 1.0, 2000.0);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void mouse ( int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN)
{
moving = 1;
startx = x;
starty = y;
}
if ( button == GLUT_LEFT_BUTTON && state == GLUT_UP )
moving = 0;

if ( button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN )
{
moving = 2;
starty = y;
}
if ( button == GLUT_RIGHT_BUTTON && state == GLUT_UP )
moving = 0;
}

void motion ( int x, int y )
{
if ( moving == 1 )
{
angle = angle + ( x – startx );
angle2 = angle2 + ( y – starty );
startx = x;
starty = y;
glutPostRedisplay ( );
}
if ( moving == 2 )
{
zoom = zoom + ( y – starty );
starty = y;
glutPostRedisplay ( );
}
}

And make sure you call
glutMouseFunc ( mouse );
glutMotionFunc ( motion );

after init() in your main loop

And needed global variables

float angle, angle2, cloud_rot;
float zoom = -25.50;

int moving, startx, starty;

See more here

Drag Mouse to move Objects
According to the docs, the mouse state has to be checkd like this:
Uint8 ms;
ms = SDL_GetMouseState(&x, &y);
if(ms & SDL_BUTTON(SDL_BUTTON_LEFT))
{
MouseButtonUp(x,y,LEFT);
}
else if (ms & SDL_BUTTON(SDL_BUTTON_RIGHT))
{
MouseButtonUp(x,y,RIGHT);
}
else if (ms & SDL_BUTTON(SDL_BUTTON_MIDDLE))
{
MouseButtonUp(x,y,MIDDLE);
}

// my mouse event code cut from my game engine.
// All the game events go thru here
while ( SDL_PollEvent(&event) )
{
// Send Keyboard events to the keyboard handler
done = HandleKeys(event);

// Mouse events
int x,y;
switch (event.type)
{
// A button on the mouse was pressed
case SDL_MOUSEBUTTONDOWN:
switch(SDL_GetMouseState(&x,&y))
{
case SDL_BUTTON(SDL_BUTTON_LEFT):
MouseButtonDown(x, y, LEFT);
break;
case SDL_BUTTON(SDL_BUTTON_RIGHT):
MouseButtonDown(x, y, RIGHT);
break;
case SDL_BUTTON(SDL_BUTTON_MIDDLE):
MouseButtonDown(x, y, MIDDLE);
break;
default:
break;
}
break;

// It was realeased
case SDL_MOUSEBUTTONUP:
switch(SDL_GetMouseState(&x, &y))
{
case SDL_BUTTON(SDL_BUTTON_LEFT):
MouseButtonUp(x, y, LEFT);
break;
case SDL_BUTTON(SDL_BUTTON_RIGHT):
MouseButtonUp(x, y, RIGHT);
break;
case SDL_BUTTON(SDL_BUTTON_MIDDLE):
MouseButtonUp(x, y, MIDDLE);
break;
default:
break;
}
break;

// Mouse is on the move.
case SDL_MOUSEMOTION:
SDL_GetMouseState(&x, &y);
MouseMove(x, y);
break;

}

http://www.gamedev.net/community/forums/topic.asp?topic_id=400975

Getting mouse button and/or keyboard events
Hi all,
I have a Windows program I am using for an experiment – I am recording people’s reaction times in various situations, and to control the duration of the displays people see, I increase the priority of the current process and the current thread using the Windows functions SetPriorityClass(hProcess,
HIGH_PRIORITY_CLASS) and SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST),
respectively. Raising the priority of the current thread locks out other
Windows processes (so they don’t affect the timing of my displays), but it also
appears to lock out the keyboard and mouse, so I can’t use SDL_PollEvent() to
get mouse button presses or key presses. I’m wondering if there is another
function that will allow me to directly poll the mouse or check for specific key
presses that would not be affected by changing the priority of the thread. I
realize that this might be beyond the scope of the forum, but any information
would be helpful and appreciated. (I also realize that recording reaction times
with a mouse or keyboard event is likely to have some built-in variability; I’m
just trying to minimize that variability as much as possible). Thank you in
advance.

Chris Dickinson
http://lists.libsdl.org/pipermail/sdl-libsdl.org/2008-October/066952.html
Maybe:
Uint8* keystates = SDL_GetKeyState(0);

if(keystates[SDLK_SPACE])
{
// do stuff
}

and… (from docs)
SDL_PumpEvents();
if(SDL_GetMouseState(NULL, NULL)&SDL_BUTTON(1))
printf(“Mouse Button 1(left) is pressed.\n”);

Jonny D


basically, if you’re just wanting a ray in the direction of the mouse click, then its pretty simple using gluUnProject.
below is a simple usage to get the ray

GLdouble ray_x, ray_y, ray_z;
GLint viewport[4];
GLdouble proj[16];
GLdouble modelview[16];

// we query OpenGL for the necessary matrices etc.
glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_PROJECTION_MATRIX, proj);
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);

// assuming you have mouse coordinates as mouseX and mouseY
// gluUnproject assumes coordinates are measured from bottom of screen
// so we invert the mouseY you got from glut or SDL or watever
GLdouble _mouseY = viewport[3] – mouseY;

// using 1.0 for winZ gives u a ray
gluUnProject(mouseX, _mouseY, 1.0f, modelview, proj, viewport, &ray_x, &ray_y, &ray_z);

and there you have the ray direction coords… it isn’t normalized tho fyi.

i think you can actually get the z coordinate of the object you clicked.. but i haven’t needed that yet… then you’d pass in something else as winZ, getting it from the Z-buffer… but not too sure.

hope that helped.
—————-
If you just want the 3d coordinates of the point in space the mouse is over, the following code will give you just that:

GLdouble model_view[16];
glGetDoublev(GL_MODELVIEW_MATRIX, model_view);
GLdouble projection[16];
glGetDoublev(GL_PROJECTION_MATRIX, projection);
GLint viewport[4];
glGetIntegerv(GL_VIEWPORT, viewport);
double dx; double dy; double dz;
GLfloat depth[2];
glReadPixels (x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depth);
gluUnProject(x, y, depth[0], model_view, projection, viewport, &dx, &dy, &dz);
x3d = float(dx);
y3d = float(dy);
z3d = float(dz);

Zoom in and out a large surface
There are 2 common ways to zoom in 3D:

  • by scaling
  • by manipulating the projection matrix

Scaling just involves calling glScalef with the correct scaling factor before rendering the zoomed object. Unfortunately, you will still run into problems with the clipping planes.

The correct way to zoom is to modify the projection matrix. If you are using an orthographic projection, just scale the width and height arguments to glOrtho. If you are using a perspective projection, try modifying the field of view (narrow field of view is more zoomed).

glTranslate is not a very good way to zoom. You are basically moving the object closer of further away from the camera, which will sort of work in perspective projection, but eventually you will translate past the a clipping plane.

I was recently doing this by changing glViewPort function and increasing the number (from both sides)
See more here

4 thoughts on “Interaction with Mouse in OpenGL (Part 2)

Leave a Reply to Nguyễn Vũ Ngọc Tùng Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.