PDA

View Full Version : How Do I Convert Mouse Position Cordinates to OpenGL cordinates?



noobscratcher
06-22-2012, 02:20 AM
Hello I'm trying really hard to do the maths here but I have no clue what to do at all when it comes to converting coordinates?


Here whats happening :

1.) I'm trying to select a area.

2.) This area that is selected is created by left clicking on the window.

3.) OpenGL puts a quad and then I put a texture with a white coloring in the center in perspective projection onto the window and my shaders colorkey out the center.

4.) Whatever is under that quad is then selected.

But the problem :

I want too snap the quad to the cursor at all times when I left click I have no idea how to do that and this is my attempt to do just that using gluUnProject and glTranslatef();

oh before I show the code I'm using

WIN32 API
OpenGL 3.0
GLSL


Heres the code :

This function is what attempts to snap the quad to the mouse but fails dramatically.


void display(){
glClearColor(0.0,0.0,0.0,1.0);


glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);


for(std::vector<GLuint>::iterator I = cube.begin(); I != cube.end(); ++I)
{

glCallList(*I);


}



if(DrawArea == true)
{

glReadPixels(winX, winY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ);


cerr << winZ << endl;


glGetDoublev(GL_MODELVIEW_MATRIX, modelview);


glGetDoublev(GL_MODELVIEW_MATRIX, projection);


glGetIntegerv(GL_VIEWPORT, viewport);


gluUnProject(winX, winY, winZ , modelview, projection, viewport, &posX, &posY, & posZ);


glBindTexture(GL_TEXTURE_2D, DrawAreaTexture);


glPixelStorei(GL_UNPACK_ALIGNMENT, 1);


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, DrawAreaSurface->w, DrawAreaSurface->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, DrawAreaSurface->pixels);


glEnable(GL_TEXTURE_2D);


glBindTexture(GL_TEXTURE_2D, DrawAreaTexture);


glTranslatef(posX , posY, posZ);


glBegin(GL_QUADS);


glTexCoord2f (0.0, 0.0);
glVertex3f(0.5, 0.5, 0);


glTexCoord2f (1.0, 0.0);
glVertex3f(0, 0.5, 0);

glTexCoord2f (1.0, 1.0);
glVertex3f(0, 0, 0);


glTexCoord2f (0.0, 1.0);
glVertex3f(0.5, 0, 0);


glEnd();





}

SwapBuffers(hDC);




//FOR SPAMMING 1/0
// cerr << DrawArea << endl;
}




This function is being called everytime in the main loop here :




while(GetMessage(&Msg, NULL, 0, 0) > 0)
{

TranslateMessage(&Msg);


DispatchMessage(&Msg);

display();

}


return Msg.wParam;
}

Dark Photon
06-22-2012, 07:43 AM
...
glGetDoublev(GL_MODELVIEW_MATRIX, modelview);
glGetDoublev(GL_MODELVIEW_MATRIX, projection);
glGetIntegerv(GL_VIEWPORT, viewport);
gluUnProject(winX, winY, winZ , modelview, projection, viewport, &posX, &posY, & posZ);


Take a look at the 2nd line above. See any problems? :whistle:

noobscratcher
06-22-2012, 09:43 AM
Ahh ha yes I didn't see that thanks for pointing that out! :)


But also how can I snap a quad to the mouse cursor? what am I required to do to succeed

Dark Photon
06-22-2012, 10:24 AM
But also how can I snap a quad to the mouse cursor?
You're on the right track.

- Install mouse event handler
- Get the X,Y window-space position of the mouse on left click
- Draw your quad around that position

noobscratcher
06-22-2012, 10:37 AM
but how do I draw the quad around that position? glTranslating with posX, PosY, posZ returns a weird flickering textured mapped quad that seems to be rendered again with the orginal quad and they flicker because of left clicking and even if I move the mouse cursor the state and position of the texture mapped quad stays the same.

noobscratcher
06-23-2012, 01:32 AM
I'm still stuck I know I have to do some conversion but that conversion makes no sense and isn't obvious to work so can someone help.

noobscratcher
06-23-2012, 07:33 AM
Can someone answer Anyone?

cireneikual
06-23-2012, 10:15 AM
I am not sure if I understand your problem correctly, but it seems like you just want to draw a 2D quad over the main scene as a selection box. Switch to ortho, disable depth testing, and render the quad at the screen coordinates of the mouse. You then un-project the mouse coordinates so you can select stuff in 3D.

noobscratcher
06-23-2012, 11:13 AM
I want the 2d quad to be center to the mouse cursor when I left click thats what I want to know how to do. :)

Nick_Miller
06-23-2012, 11:41 AM
Okay, soo.. it seems that you are trying to fuss with glTranslate is what I've been gathering. Depending on the OpenGL state, you may not get the results you expect (this can be true for many functions).

Anyways, I have two suggestions:
1. Make sure glTranslate is being called in the correct matrix mode. The correct matrix mode for you should be set using


glMatrixMode(GL_MODELVIEW)
If you have the GL_PROJECTION matrix set, you will be translating the camera, which isn't probably what you are intending to do.


2. Try deleting the glTranslate method alltogether. Instead, you should take the x, y, values from the mouse coordinate, and use them directly to change the location/dimension of the actual square.

Here's an example of what I mean:



if(screen_selected)//If the mouse is pressed on the screen, then draw the square
{
/*This example is ignoring texture requirements, however you can just put those in as before.
Also, this uses the variables "initalMouseX" and "initalMouseY" which represent the XY coordinate of the mouse when the use clicks the mouse.
The variables "currentMouseX", and "currentMouseY" represent the current XY coordinates of the mouse while the use still has the mouse button down. The reason we see "screenHeight - initalMouseY" or "screenHeight - currentMouseY" is because most implements of 2D graphics measures the mouse coordinate from the top-left corner of the screen. Therefore, we need to flip the Y coordinate so that it matches the implementation of OpenGL which is typically the bottom-left corner.*/
glBegin(GL_QUADS);
glVertex3d(initalMouseX, screenHeight - initialMouseY, 0);
glVertex3d(initalMouseX, screenHeight - currentMouseY, 0);
glVertex3d(currentMouseX, screenHeight - currentMouseY, 0);
glVertex3d(currentMouseX, screenHeight - initialMouseY, 0);
glEnd();
}
//There should now be a quad, parallel with the screen.


Comparing this to a 2D implementation I've made before (for group-selecting file icons), the above example seems as if it would work as is, simply because OpenGL does things differently. However, in that file-selector program, I had to do some other mathematics to keep the selection box the correct size. For that I measured what size it should be, then I translated it accordingly to fit the region selected.

Hope this helps! Let me know how you are doing with this.

noobscratcher
06-23-2012, 12:00 PM
Thank you I will try this today or tomorrow defently I think I might finally start understanding how to snap to certain areas in opengl thanks too yours truely :D

noobscratcher
06-24-2012, 01:21 AM
Okay I've tried to do what you ask and having issues first of all the quad doesn't show anymore even tho I followed everything you have written in that post above here is my code

glTexCoord2f (0.0, 0.0);
glVertex3f(pos.x, SCREEN_HEIGHT - pos.y, 0);


glTexCoord2f (1.0, 0.0);
glVertex3f(pos.x , SCREEN_HEIGHT - currentMouseY, 0);

glTexCoord2f (1.0, 1.0);
glVertex3f(currentMouseX , SCREEN_HEIGHT - currentMouseY , 0);


glTexCoord2f (0.0, 1.0);
glVertex3f(currentMouseX , SCREEN_HEIGHT - pos.y , 0);


glEnd();

the values currentMouseX, currentMouseY are being set when the WM_LBUTTONDOWN command is called in Win32 which represents the left button down mouse click

maybe if you see my full source you can pin point where I might be going wrong then I can learn from this in the future if I ever have this issue again :) .

here is the link to the full source the code is abit messy sorry about that -> http://pastebin.com/0WUAh9t4 line 432 to 510 is where most of the code we talked about is being called.

I hope this helps you helping me figure this problem out.

noobscratcher
06-24-2012, 05:29 AM
anyone? :)

cireneikual
06-24-2012, 06:35 AM
Did you use an orthographic projection? Depending on how you set up the orthographic projection, you can make matrix transformations follow pixels - a glTranslatef(200, 200, 0); would move it 200 pixels in the x and y directions. Something like this:




glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, screenWidth, 0, screenHeight, -1, 1);
glMatrixMode(GL_MODELVIEW);


glDisable(GL_DEPTH_TEST);

glLoadIdentity();
glTranslatef(mouse_window_posX, mouse_window_posY, 0.0f);


// Draw the quad...


glEnable(GL_DEPTH_TEST);


// .........

noobscratcher
06-24-2012, 06:47 AM
Using orthographic projection wouldn't help me in this situation would It Oh I see! your saying that orthographic projection will be the closest to mouse cursor position so go into orthographic projection and render?

Nick_Miller
06-24-2012, 11:35 AM
With only skimming certain parts of the code, I want to ask a couple questions that can help point you in the right direction. (Please note I have little to no experiece in C++ and primarily work with Java. However, I did comprehend much of the code).

As said by cireneikual:

Did you use an orthographic projection?
This is important because you are giving screen coorindates to OpenGL. If you are in perspective mode, your quad will be HUGE.

1. I noticed you are using shaders. Are your shaders working properly? Will they render geometry given you specify everything right?
2. Is texturing working? Make sure you are not drawing an invisible quad. Try setting the color of the quad to something different than the clear color.
3. Make sure that your viewing paramters are correct. You won't be able to see the quad if your camera is facing the wrong direction.
For debugging you may want to insert the following into your modelview projection area:

//cameraPos is the coordinate of the camera, lookAtPos is where the camera is looking and the last 3 values specify an upward vector.
gluLookAt(cameraPos.x, cameraPos.y, cameraPos.z, lookAtPos.x, lookAtPos.y, lookAtPos.z, 0, 1, 0);

4. Can you render anything at all? Try putting some piece of code that you know will work and see if you can render a simple object using constant coordinate values.
5. I don't know if this is a big C++ problem, but in Java, thread concurrency matters a ton: Are the variables you have setup NULL or 0? Make sure that pos.x actually gives the value you want it to.
6. What is the glTranslatef() doing? Do you still need it? If you are not in orthographic projection mode, it could be moving the quad far out of the scene. (Originally, I didn't think you needed it, and you could instead create dynamic geometry. This is why I said to put variables in place of the quad's location/dimension.)

Also I want to suggest that you setup projection and modelview matrices each pass through the display() method. If you are rendering perspective and orthographic projections, you MUST do this. Otherwise, you will stay in the last mode specified.

Also, I noticed a subtle but big error in your perspective mode setup in the init() function:

This is what you have

gluPerspective(90 SCREEN_HEIGHT/SCREEN_WIDTH, -1.0, 1.0);
This is what you should have

gluPerspective(90 SCREEN_HEIGHT/SCREEN_WIDTH, 0.01, 1.0);
This is because the near-clipping plane cannot be less than or equal to zero. Therefore, make it barely positive. ;)


Best of luck!