[SDL] Translating mouse coordinates in SDL into OpenGL space

Started by
13 comments, last by adam_o 16 years, 2 months ago
I know I've seen the code for this somewhere, but I can't remember, so I'm calling upon your superior memories to help me figure this out: when SDL outputs coordinates, it outputs them in 2D, "screen-level" coordinates. Now from that I would like to figure out how to determine what the mouse would have "touched" in a 2D or 3D OpenGL environment. Is there something that would figure this out for me somehow? All help is appreciated and thanks in advance. adam_o
_______________________My computer stats:Xcode 3.1.2Mac OS 10.5.8---Visual C++ 2008 Express EditionWindows XP---NetBeansUbuntu 9.04---Help needed here!
Advertisement
It sounds like you're looking for gluUnProject. It takes screen-space coordinates and returns world-space coordinates, based on the passed viewport and matrices. For help on determining what the user is trying to click on, google around for "opengl mouse picking" (the first result is one simple and common way to do it, though faster methods do exist).
Quote:Original post by jouley
It sounds like you're looking for gluUnProject. It takes screen-space coordinates and returns world-space coordinates, based on the passed viewport and matrices. For help on determining what the user is trying to click on, google around for "opengl mouse picking" (the first result is one simple and common way to do it, though faster methods do exist).


Ok, thank you. I'll try to work with that, and if I have any more problems, I'll post again.
_______________________My computer stats:Xcode 3.1.2Mac OS 10.5.8---Visual C++ 2008 Express EditionWindows XP---NetBeansUbuntu 9.04---Help needed here!
I finally got around to trying out gluUnProject(), but my program crashed and the data was wrong. So I tried gluProject() (because I figured it might be the other way around; I'm using mouse coordinates to find what the mouse clicked on) and it gave me weird numbers, but I got the numbers. The problem is, with both versions of Project(), my program crashes, and if I simply comment the Project() code, the program works fine. Here's my code:

int x_loc = event.button.x;int y_loc = event.button.y;fileout << "(" << x_loc << "," << y_loc << ")" << endl << flush;GLdouble mv_matrix;GLdouble prj_matrix;GLint vp;GLdouble xdest, ydest, zdest;glGetDoublev(GL_MODELVIEW, &mv_matrix);glGetDoublev(GL_PROJECTION, &prj_matrix);glGetIntegerv(GL_VIEWPORT, &vp);gluProject(x_loc, y_loc, 0, &mv_matrix, &prj_matrix, &vp,	&xdest, &ydest, &zdest);fileout << "(" << xdest << ", " << ydest << ", "	<< zdest << ")" << endl << flush;

And here's what I got:
(431,82)(504.471, 380.626, -0.108788)(14,37)(504.471, 383.39, -0.10159)(433,329)(504.471, 378.919, -0.113231)(222,153)(504.471, 379.571, -0.111534)(74,332)(504.471, 378.914, -0.113244)
(these are five random points on the screen, SDL coordinate pairs first and OpenGL triples second)

So am I using this code wrong? Why is it hanging up? Is it gluProject() or gluUnproject()?

EDIT: I'd like to add that the program crashes iff I click the mouse button (which activates glu*Project()). Otherwise, it runs just fine. Another weird thing to note is that it crashes on exit, not when I click the button.

[Edited by - adam_o on January 21, 2008 9:57:14 PM]
_______________________My computer stats:Xcode 3.1.2Mac OS 10.5.8---Visual C++ 2008 Express EditionWindows XP---NetBeansUbuntu 9.04---Help needed here!
Quote:Original post by adam_o
I finally got around to trying out gluUnProject()...
Which is the function you're looking for. gluProject is used to turn world space coordinates into screen space
Quote:...but my program crashed and the data was wrong.
Taking a look at your code, I've commented some trouble spots:
int x_loc = event.button.x;int y_loc = event.button.y;fileout << "(" << x_loc << "," << y_loc << ")" << endl << flush;//  you create one GLdouble here, but glGetDoublev will try to fill the//  pointed-at space with 16 doubles (each element of a 4x4 matrix).GLdouble mv_matrix;  //  should be: GLdouble mv_matrix[16];GLdouble prj_matrix;  //  likewiseGLint vp;  //  here, the viewport will only hold 4 valuesGLdouble xdest, ydest, zdest;glGetDoublev(GL_MODELVIEW, &mv_matrix);glGetDoublev(GL_PROJECTION, &prj_matrix);glGetIntegerv(GL_VIEWPORT, &vp);gluProject(x_loc, y_loc, 0, &mv_matrix, &prj_matrix, &vp,	&xdest, &ydest, &zdest);fileout << "(" << xdest << ", " << ydest << ", "	<< zdest << ")" << endl << flush;

Quote:So am I using this code wrong? Why is it hanging up? Is it gluProject() or gluUnproject()?
To summarize: Yep. Because it's trying to write to memory space it doesn't own. gluUnProject( ).

Quote:EDIT: I'd like to add that the program crashes iff I click the mouse button (which activates glu*Project()). Otherwise, it runs just fine. Another weird thing to note is that it crashes on exit, not when I click the button.
The crash only happens iff you click because nothing is going wrong otherwise, meaning the problem is definitely within the given code. The crash happening on exit is just how this particular bug has chosen to manifest itself. You're lucky it didn't turn your oven on for you. The garbage numbers you were getting is likely because the values from one matrix were overwriting those from the others, since the allocated space was contiguous. You can learn more about the glGet* functions here, including what their parameters/return values are.

Best of luck!
-jouley
I just tried what you suggested, but got these errors:

92: error: cannot convert 'GLdouble (*)[4][4]' to 'GLdouble*' for argument '2' to 'void glGetDoublev(GLenum, GLdouble*)'
(etc)

So it says that the second argument of glGetDoublev is not a 4x4 array.

EDIT: An interesting thing that I found is that under the link you gave me (*Mac shudders) is that the enum is GL_MODELVIEW_MATRIX, not GL_MODELVIEW. I'll test this out and edit again with results.
_______________________My computer stats:Xcode 3.1.2Mac OS 10.5.8---Visual C++ 2008 Express EditionWindows XP---NetBeansUbuntu 9.04---Help needed here!
Something that warranted a new post... when I changed the code to this:
int x_loc = event.button.x;int y_loc = event.button.y;fileout << "(" << x_loc << "," << y_loc << ")" << endl << flush;GLdouble mv_matrix;GLdouble prj_matrix;GLint vp;GLdouble xdest, ydest, zdest;glGetDoublev(GL_MODELVIEW_MATRIX, &mv_matrix);glGetDoublev(GL_PROJECTION_MATRIX, &prj_matrix);glGetIntegerv(GL_VIEWPORT, &vp);gluProject(x_loc, y_loc, 0, &mv_matrix, &prj_matrix, &vp,	&xdest, &ydest, &zdest);fileout << "(" << xdest << ", " << ydest << ", "	<< zdest << ")" << endl << flush;

The debugger came up as usual, but it did shut itself off after printing this:
Loading program into debugger…GNU gdb 6.3.50-20050815 (Apple version gdb-768) (Tue Oct  2 04:11:19 UTC 2007)Copyright 2004 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB.  Type "show warranty" for details.This GDB was configured as "powerpc-apple-darwin".Program loaded.sharedlibrary apply-load-rules allAttaching to program: `/Users/atg/Desktop/Projects/Xcode Projects/Release/Tetris_020.app/Contents/MacOS/Tetris_020', process 864.gdb stack crawl at point of internal error:[ 0 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (align_down+0x0) [0x11d4fc][ 1 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (frame_register+0x98) [0x123c6c][ 2 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (frame_register_read+0x2c) [0x123d78][ 3 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (do_frame_register_read+0x10) [0x123dc0][ 4 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (regcache_save+0xd8) [0x2b900][ 5 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (frame_save_as_regcache+0x4c) [0x122b88][ 6 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (frame_pop+0x20) [0x124e64][ 7 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (hand_function_call+0xde4) [0x5e38c][ 8 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (allocate_space_in_inferior_malloc+0xc8) [0x38e80][ 9 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (macosx_allocate_space_in_inferior_helper+0x24) [0x18265c][ 10 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (catch_exceptions_with_msg+0x5c) [0x76568][ 11 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (macosx_allocate_space_in_inferior+0x88) [0x182704][ 12 ] /Developer/usr/libexec/gdb/gdb-powerpc-apple-darwin (value_string+0x15c) [0x3e1a8]/SourceCache/gdb/gdb-768/src/gdb/frame.c:661: internal-error: frame_register: Assertion `frame != NULL && frame->next != NULL' failed.A problem internal to GDB has been detected,further debugging may prove unreliable.The Debugger Debugger is attaching to process(gdb) 
Now I know that the 0-12 list is something very important, but I have no clue what, as I do not know how to use this newer version of XCode. If you know what it means, that would be helpful, but I think I may have to go to the Mac mailing lists for this.
_______________________My computer stats:Xcode 3.1.2Mac OS 10.5.8---Visual C++ 2008 Express EditionWindows XP---NetBeansUbuntu 9.04---Help needed here!
OpenGL uses a 16 element one-dimensional array for its matrices.
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other player's eyes with his King.
Quote:Original post by smart_idiot
OpenGL uses a 16 element one-dimensional array for its matrices.


I understand this. I have understood this from my first day programming OpenGL. Your brief "helpfulness" didn't do anything. I suggest if you really want to help, that you go over this topic and see what I mean. Otherwise, waste your time in the Lounge.
_______________________My computer stats:Xcode 3.1.2Mac OS 10.5.8---Visual C++ 2008 Express EditionWindows XP---NetBeansUbuntu 9.04---Help needed here!
Quote:Original post by adam_o
Quote:Original post by smart_idiot
OpenGL uses a 16 element one-dimensional array for its matrices.


I understand this. I have understood this from my first day programming OpenGL. Your brief "helpfulness" didn't do anything. I suggest if you really want to help, that you go over this topic and see what I mean. Otherwise, waste your time in the Lounge.


The hardest things to learn are the things you think you already know.

double modelMatrix[16]; // <-- A one dimensional array, with 16 elements.double projMatrix[16];int    viewport[4];glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix);glGetDoublev(GL_PROJECTION_MATRIX, projMatrix);glGetIntegerv(GL_VIEWPORT, viewport);gluUnProject(mouse_x, viewport[3]-mouse_y, mouse_depth, modelMatrix, projMatrix, viewport, &position_x, &position_y, &position_z);


The value for mouse_depth is a tricky value to get, how far into the screen is the mouse? You can either use gluProject on a known point, and use its depth, making the mouse as far into the screen as that point is, or you can read the data from the depth buffer, and use the point under the mouse, in which case it will follow the surface of the geometry being rendered.
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other player's eyes with his King.

This topic is closed to new replies.

Advertisement