{"id":884,"date":"2009-09-23T18:30:00","date_gmt":"2009-09-23T17:30:00","guid":{"rendered":"http:\/\/it4bus.vn\/itersdesktop\/2009\/09\/23\/interaction-with-mouse-in-opengl-part-2\/"},"modified":"2013-12-01T01:31:12","modified_gmt":"2013-12-01T00:31:12","slug":"interaction-with-mouse-in-opengl-part-2","status":"publish","type":"post","link":"https:\/\/www.itersdesktop.com\/fr\/2009\/09\/23\/interaction-with-mouse-in-opengl-part-2\/","title":{"rendered":"Interaction with Mouse in OpenGL (Part 2)"},"content":{"rendered":"<p>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&rsquo;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.<\/p>\n<p><span>Moving selected objects in OpenGL<\/span><br \/>\nWhat you need to do is check whenever the mouse is moved <span>AND<\/span> 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.<\/p>\n<p>Here&rsquo;s the steps:<br \/>\n1. User mouse clicks down on object<br \/>\n2. Call function with mouse down<br \/>\n3. User keeps mouse held down and moves mouse<br \/>\n4. Call function with mouse motion<br \/>\n5. User stops holding mouse down<br \/>\n6. Call function with mouse up<\/p>\n<p>void reshape(int w, int h) {<br \/>\nglViewport(0, 0, (GLint) w, (GLint) h);<br \/>\nglMatrixMode(GL_PROJECTION);<br \/>\nglLoadIdentity();<br \/>\nif ( h==0 )<br \/>\ngluPerspective(45, (GLdouble)w, 1.0, 2000.0);<br \/>\nelse<br \/>\ngluPerspective(45, (GLdouble)w\/ (GLdouble)h, 1.0, 2000.0);<\/p>\n<p>glMatrixMode(GL_MODELVIEW);<br \/>\nglLoadIdentity();<br \/>\n}<\/p>\n<p>void mouse ( int button, int state, int x, int y) {<br \/>\nif (button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_DOWN)<br \/>\n{<br \/>\nmoving = 1;<br \/>\nstartx = x;<br \/>\nstarty = y;<br \/>\n}<br \/>\nif ( button == GLUT_LEFT_BUTTON &amp;&amp; state == GLUT_UP )<br \/>\nmoving = 0;<\/p>\n<p>if ( button == GLUT_RIGHT_BUTTON &amp;&amp; state == GLUT_DOWN )<br \/>\n{<br \/>\nmoving = 2;<br \/>\nstarty = y;<br \/>\n}<br \/>\nif ( button == GLUT_RIGHT_BUTTON &amp;&amp; state == GLUT_UP )<br \/>\nmoving = 0;<br \/>\n}<\/p>\n<p>void motion ( int x, int y )<br \/>\n{<br \/>\nif ( moving == 1 )<br \/>\n{<br \/>\nangle = angle + ( x &#8211; startx );<br \/>\nangle2 = angle2 + ( y &#8211; starty );<br \/>\nstartx = x;<br \/>\nstarty = y;<br \/>\nglutPostRedisplay ( );<br \/>\n}<br \/>\nif ( moving == 2 )<br \/>\n{<br \/>\nzoom = zoom + ( y &#8211; starty );<br \/>\nstarty = y;<br \/>\nglutPostRedisplay ( );<br \/>\n}<br \/>\n}<\/p>\n<p>And make sure you call<br \/>\nglutMouseFunc ( mouse );<br \/>\nglutMotionFunc ( motion );<\/p>\n<p>after init() in your main loop<\/p>\n<p>And needed global variables<\/p>\n<p>float angle, angle2, cloud_rot;<br \/>\nfloat zoom = -25.50;<\/p>\n<p>int moving, startx, starty;<\/p>\n<p>See more <a href=\"http:\/\/www.opengl.org\/discussion_boards\/ubbthreads.php?ubb=showflat&amp;Number=260174\" target=\"_blank\">here<\/a><\/p>\n<p><span>Drag Mouse to move Objects<\/span><br \/>\nAccording to the docs, the mouse state has to be checkd like this:<br \/>\nUint8 ms;<br \/>\nms = SDL_GetMouseState(&amp;x, &amp;y);<br \/>\nif(ms &amp; SDL_BUTTON(SDL_BUTTON_LEFT))<br \/>\n{<br \/>\nMouseButtonUp(x,y,LEFT);<br \/>\n}<br \/>\nelse if (ms &amp; SDL_BUTTON(SDL_BUTTON_RIGHT))<br \/>\n{<br \/>\nMouseButtonUp(x,y,RIGHT);<br \/>\n}<br \/>\nelse if (ms &amp; SDL_BUTTON(SDL_BUTTON_MIDDLE))<br \/>\n{<br \/>\nMouseButtonUp(x,y,MIDDLE);<br \/>\n}<\/p>\n<p>\/\/ my mouse event code cut from my game engine.<br \/>\n\/\/ All the game events go thru here<br \/>\nwhile ( SDL_PollEvent(&amp;event) )<br \/>\n{<br \/>\n\/\/ Send Keyboard events to the keyboard handler<br \/>\ndone = HandleKeys(event);<\/p>\n<p>\/\/ Mouse events<br \/>\nint x,y;<br \/>\nswitch (event.type)<br \/>\n{<br \/>\n\/\/ A button on the mouse was pressed<br \/>\ncase SDL_MOUSEBUTTONDOWN:<br \/>\nswitch(SDL_GetMouseState(&amp;x,&amp;y))<br \/>\n{<br \/>\ncase SDL_BUTTON(SDL_BUTTON_LEFT):<br \/>\nMouseButtonDown(x, y, LEFT);<br \/>\nbreak;<br \/>\ncase SDL_BUTTON(SDL_BUTTON_RIGHT):<br \/>\nMouseButtonDown(x, y, RIGHT);<br \/>\nbreak;<br \/>\ncase SDL_BUTTON(SDL_BUTTON_MIDDLE):<br \/>\nMouseButtonDown(x, y, MIDDLE);<br \/>\nbreak;<br \/>\ndefault:<br \/>\nbreak;<br \/>\n}<br \/>\nbreak;<\/p>\n<p>\/\/ It was realeased<br \/>\ncase SDL_MOUSEBUTTONUP:<br \/>\nswitch(SDL_GetMouseState(&amp;x, &amp;y))<br \/>\n{<br \/>\ncase SDL_BUTTON(SDL_BUTTON_LEFT):<br \/>\nMouseButtonUp(x, y, LEFT);<br \/>\nbreak;<br \/>\ncase SDL_BUTTON(SDL_BUTTON_RIGHT):<br \/>\nMouseButtonUp(x, y, RIGHT);<br \/>\nbreak;<br \/>\ncase SDL_BUTTON(SDL_BUTTON_MIDDLE):<br \/>\nMouseButtonUp(x, y, MIDDLE);<br \/>\nbreak;<br \/>\ndefault:<br \/>\nbreak;<br \/>\n}<br \/>\nbreak;<\/p>\n<p>\/\/ Mouse is on the move.<br \/>\ncase SDL_MOUSEMOTION:<br \/>\nSDL_GetMouseState(&amp;x, &amp;y);<br \/>\nMouseMove(x, y);<br \/>\nbreak;<\/p>\n<p>}<\/p>\n<p>http:\/\/www.gamedev.net\/community\/forums\/topic.asp?topic_id=400975<\/p>\n<p><span>Getting mouse button and\/or keyboard events<\/span><br \/>\nHi all,<br \/>\nI have a Windows program I am using for an experiment &#8211; I am recording people&rsquo;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,<br \/>\nHIGH_PRIORITY_CLASS) and SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST),<br \/>\nrespectively. Raising the priority of the current thread locks out other<br \/>\nWindows processes (so they don&rsquo;t affect the timing of my displays), but it also<br \/>\nappears to lock out the keyboard and mouse, so I can&rsquo;t use SDL_PollEvent() to<br \/>\nget mouse button presses or key presses. I&rsquo;m wondering if there is another<br \/>\nfunction that will allow me to directly poll the mouse or check for specific key<br \/>\npresses that would not be affected by changing the priority of the thread. I<br \/>\nrealize that this might be beyond the scope of the forum, but any information<br \/>\nwould be helpful and appreciated. (I also realize that recording reaction times<br \/>\nwith a mouse or keyboard event is likely to have some built-in variability; I&rsquo;m<br \/>\njust trying to minimize that variability as much as possible). Thank you in<br \/>\nadvance.<\/p>\n<p>Chris Dickinson<br \/>\nhttp:\/\/lists.libsdl.org\/pipermail\/sdl-libsdl.org\/2008-October\/066952.html<br \/>\nMaybe:<br \/>\nUint8* keystates = SDL_GetKeyState(0);<br \/>\n&#8230;<br \/>\nif(keystates[SDLK_SPACE])<br \/>\n{<br \/>\n\/\/ do stuff<br \/>\n}<\/p>\n<p>and&#8230; (from docs)<br \/>\nSDL_PumpEvents();<br \/>\nif(SDL_GetMouseState(NULL, NULL)&amp;SDL_BUTTON(1))<br \/>\nprintf(\u00ab\u00a0Mouse Button 1(left) is pressed.\\n\u00a0\u00bb);<\/p>\n<p>Jonny D<\/p>\n<hr size=\"1\" \/>\n<p>basically, if you&rsquo;re just wanting a ray in the direction of the mouse click, then its pretty simple using gluUnProject.<br \/>\nbelow is a simple usage to get the ray<\/p>\n<p>GLdouble ray_x, ray_y, ray_z;<br \/>\nGLint viewport[4];<br \/>\nGLdouble proj[16];<br \/>\nGLdouble modelview[16];<\/p>\n<p>\/\/ we query OpenGL for the necessary matrices etc.<br \/>\nglGetIntegerv(GL_VIEWPORT, viewport);<br \/>\nglGetDoublev(GL_PROJECTION_MATRIX, proj);<br \/>\nglGetDoublev(GL_MODELVIEW_MATRIX, modelview);<\/p>\n<p>\/\/ assuming you have mouse coordinates as mouseX and mouseY<br \/>\n\/\/ gluUnproject assumes coordinates are measured from bottom of screen<br \/>\n\/\/ so we invert the mouseY you got from glut or SDL or watever<br \/>\nGLdouble _mouseY = viewport[3] &#8211; mouseY;<\/p>\n<p>\/\/ using 1.0 for winZ gives u a ray<br \/>\ngluUnProject(mouseX, _mouseY, 1.0f, modelview, proj, viewport, &amp;ray_x, &amp;ray_y, &amp;ray_z);<\/p>\n<p>and there you have the ray direction coords&#8230; it isn&rsquo;t normalized tho fyi.<\/p>\n<p>i think you can actually get the z coordinate of the object you clicked.. but i haven&rsquo;t needed that yet&#8230; then you&rsquo;d pass in something else as winZ, getting it from the Z-buffer&#8230; but not too sure.<\/p>\n<p>hope that helped.<br \/>\n&#8212;&#8212;&#8212;&#8212;&#8212;-<br \/>\nIf you just want the 3d coordinates of the point in space the mouse is over, the following code will give you just that:<\/p>\n<p>GLdouble model_view[16];<br \/>\nglGetDoublev(GL_MODELVIEW_MATRIX, model_view);<br \/>\nGLdouble projection[16];<br \/>\nglGetDoublev(GL_PROJECTION_MATRIX, projection);<br \/>\nGLint viewport[4];<br \/>\nglGetIntegerv(GL_VIEWPORT, viewport);<br \/>\ndouble dx; double dy; double dz;<br \/>\nGLfloat depth[2];<br \/>\nglReadPixels (x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, depth);<br \/>\ngluUnProject(x, y, depth[0], model_view, projection, viewport, &amp;dx, &amp;dy, &amp;dz);<br \/>\nx3d = float(dx);<br \/>\ny3d = float(dy);<br \/>\nz3d = float(dz);<\/p>\n<p><span>Zoom in and out a large surface<\/span><br \/>\nThere are 2 common ways to zoom in 3D:<\/p>\n<ul>\n<li>by scaling<\/li>\n<li>by manipulating the projection matrix<\/li>\n<\/ul>\n<p>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.<\/p>\n<p>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).<\/p>\n<p>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.<\/p>\n<p>I was recently doing this by changing glViewPort function and increasing the number (from both sides)<br \/>\nSee more <a href=\"http:\/\/www.opengl.org\/resources\/faq\/technical\/viewing.htm\" target=\"_blank\">here<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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.&hellip; <\/p>\n","protected":false},"author":2,"featured_media":988,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[26,284],"tags":[575,320],"class_list":["post-884","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cpp","category-opengl","tag-opengl","tag-mouse-interaction"],"_links":{"self":[{"href":"https:\/\/www.itersdesktop.com\/fr\/wp-json\/wp\/v2\/posts\/884","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.itersdesktop.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.itersdesktop.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.itersdesktop.com\/fr\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.itersdesktop.com\/fr\/wp-json\/wp\/v2\/comments?post=884"}],"version-history":[{"count":2,"href":"https:\/\/www.itersdesktop.com\/fr\/wp-json\/wp\/v2\/posts\/884\/revisions"}],"predecessor-version":[{"id":992,"href":"https:\/\/www.itersdesktop.com\/fr\/wp-json\/wp\/v2\/posts\/884\/revisions\/992"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.itersdesktop.com\/fr\/wp-json\/wp\/v2\/media\/988"}],"wp:attachment":[{"href":"https:\/\/www.itersdesktop.com\/fr\/wp-json\/wp\/v2\/media?parent=884"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.itersdesktop.com\/fr\/wp-json\/wp\/v2\/categories?post=884"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.itersdesktop.com\/fr\/wp-json\/wp\/v2\/tags?post=884"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}