Sign in to follow this  
luckyyyyyy

OpenGL Incorrect 3D coordinates from 2D mouse click ?

Recommended Posts

luckyyyyyy    145
I want to get the mouse click position in 3D. Below is my code, its simple, I am not doing wrong in it but I don't know why I am always getting X and Y values are wrong. I think Maximum X = 0.072345664 and Y = 0.04124355 . something like this. where I am doing wrong.. ? Why I am not getting the exact values of x and y ? Z value is OK. Only issue with X and Y. any idea ? Thanks


[CODE]
void glPerspective()
{
glViewport(0, 0, WINDOW_SIZE_W, WINDOW_SIZE_H);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLdouble)WINDOW_SIZE_W / (GLdouble)WINDOW_SIZE_H, 0.1, 100000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, m_zoom, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glPerspective(); // perspective view
Some_rotation_and_translation();
Render_Triangular_model();
glPopMatrix();
swapbuffer();
}
GLpoint GetOGLMousePos(GLint x, GLint y)
{
GLdouble winX = 0.0, winY = 0.0, winZ = 0.0;
GLdouble posX = 0.0, posY = 0.0, posZ = 0.0;
GLint OGLMviewport[4]; //stores viewport information
GLdouble OGLMmodelview[16];
GLdouble OGLMprojection[16];
glGetDoublev( GL_PROJECTION_MATRIX, OGLMprojection );
glGetDoublev( GL_MODELVIEW_MATRIX, OGLMmodelview );
glGetIntegerv( GL_VIEWPORT, OGLMviewport ); //transfers viewport info into viewport array.
winX = (float)x;
winY = (float)OGLMviewport[3] - (float)y; // invert winY so that down lowers value
glReadPixels( x, GLint(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
gluUnProject( winX, winY, winZ, OGLMmodelview, OGLMprojection, OGLMviewport, &posX, &posY, &posZ);
return GLpoint(posX, posY, posZ);
}
[/CODE]

Output 3D coordinates (top right section of the OpenGL display screen):

[CODE]-0.000810418, 0.0011706, 99.9
0.00288149, 0.00126065, 99.9
0.00981506, 0.00144074, 99.9
0.0157581, 0.00171088, 99.9
0.0249429, 0.00171088, 99.9
0.0367389, 0.00180093, 99.9
0.0468241, 0.00180093, 99.9
0.0557387, 0.00225116, 99.9
0.065914, 0.00243125, 99.9
-0.000990511, 0.0105354, 99.9
-0.0013507, 0.017379, 99.9
-0.0013507, 0.0225116, 99.9
-0.00171088, 0.0268338, 99.9
-0.00171088, 0.0313362, 99.9
-0.00207107, 0.0380896, 99.9
0.0724874, 0.0404308, 99.9
0.0744684, 0.0411512, 99.9 // top right corner[/CODE]

[quote]
Think of Design with Dimensions
http://real3d.pk
[/quote] Edited by luckyyyyyy

Share this post


Link to post
Share on other sites
MarkS    3502
My guess is that is is somewhere in the GLpoint class. Your code is nearly exactly like mine and it works for me. How do you define GLpoint? That isn't part of OpenGL.

Share this post


Link to post
Share on other sites
WiredCat    1452
hey dude first thing is your perspective calculation (the z near z far problem!)


[CODE]
void T3DPlanet::GetOGLPos(int x, int y, t3dpoint & np, t3dpoint & fp)
{
glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
// glGetDoublev( GL_PROJECTION_MATRIX, projection );
glMatrixMode(GL_PROJECTION); // Change Matrix Mode to Projection
glPushMatrix();
glLoadIdentity(); // Reset View
gluPerspectiveA(90.0f, DISPLAY_WIDTH/DISPLAY_HEIGHT,1000.0f, 2000.0f); // Do the perspective calculations. Last value = max clipping depth
glGetDoublev( GL_PROJECTION_MATRIX, projection );
glPopMatrix();
glMatrixMode(GL_MODELVIEW);

// int i;
// for (i=0; i<16;i++) ShowMessage(FloatToStr(projection[i]));
glGetIntegerv( GL_VIEWPORT, viewport );
double nx,ny,nz; double fx,fy,fz;
float winX = float(x);
float winY = float(viewport[3]) - float(y);
t3dpoint neara;
t3dpoint fara;
gluUnProject(winX, winY, 0, modelview, projection, viewport, &nx, &ny, &nz);
gluUnProject(winX, winY, 1, modelview, projection, viewport, &fx, &fy, &fz);
np.x = nx;
np.y = ny;
np.z = nz;
NEAR_HIT = np;
fp.x = fx;// - nx;
fp.y = fy;// - ny;
fp.z = fz;// - nz;
FAR_HIT = fp;
}

and heres a thing that i use when mouse cursor is moving through window and it uses the proc above


[code]
void __fastcall T3DPlanet::MouseInsertMove(int X, int Y,HWND hwnd)
{

glViewport(0, 0, int( DISPLAY_WIDTH), int(DISPLAY_HEIGHT)); // Set the viewport for the OpenGL window
glMatrixMode(GL_PROJECTION); // Change Matrix Mode to Projection
glLoadIdentity(); // Reset View
gluPerspectiveA(90.0, DISPLAY_WIDTH/DISPLAY_HEIGHT,1000.0f, 1000.0 * 1000.0 * 1000.0 * 1000.0); // Do the perspective calculations. Last value = max clipping depth
glMatrixMode(GL_MODELVIEW);

sx = X;
sy = Y;
//glClear(GL_COLOR_BUFFER_BIT);
//glClear(GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glLoadIdentity();
gluLookAt(EYEPOS.x,EYEPOS.y,EYEPOS.z,EYEPOS.x+EYELOOKATPOINT.x,
EYEPOS.y-EYELOOKATPOINT.y,EYEPOS.z-EYELOOKATPOINT.z,
0,1,0);
if (insert_mode == true) {
TPoint mouse;
GetCursorPos(&mouse); // Gets The Current Cursor Coordinates (Mouse Coordinates)
ScreenToClient(hwnd, &mouse);
t3dpoint np, fp;
GetOGLPos(mouse.x,mouse.y,np,fp);
t3dpoint vLine[2];
np = vectorAB(NEAR_HIT,FAR_HIT);
np = Normalize( np ); //nice one milion kilometers away ;u
np = vector_multiple(np, 1000.0f * 1000.0f * 1000.0f);
vLine[0] = NEAR_HIT;
vLine[1] = vectors_add(NEAR_HIT, np);
//
//
int i;
for (i=0; i<SCENE_SELECTION[0].selectedfaces.Length;i++)
if (LineIntersectFaceFromModel(SCENE_SELECTION[0].selectedfaces[i],PLANET_MODEL,vLine, HIT_SPACE_POSITION ) == true)
return;
}
glPopMatrix();
}
[/code]
[/CODE]


Ah please dont ask me why i call perspective projection and loadidentity before getoglpos ( i cant remember!!!)
well i remember that just draw your scene then use getoglpos


but it returns me two POINTS (NOT THE DEPTH POINT or etc) just 2 points that make the line from screen to the outter space ;x
then i must find a collision point between polygon ray intersection


I think you can bypass ray poly intersection by reading the acutal depth value from image (by glReadPixels let assume that will be a var called KKK)

so then gluUnProject(winX, winY, KKK, modelview, projection, viewport, &nx, &ny, &nz); nx ny nz are output pos vals but i don't know if it works

===================

and here's a proove that it works :X but watch after 1 min :/

[media]http://www.youtube.com/watch?v=YAeedDLS7aE&feature=youtu.be[/media] Edited by ___

Share this post


Link to post
Share on other sites
luckyyyyyy    145
I have tried everything but not getting the exact X and Y values. I am applying glPerspective() in real-time (display function) thats why I think I have to apply it with a specific matrix but i dont know which matrix. I do not want to select vertex or something like that I just need 3D coordinates at the click position.


[quote]
Think of Design with Dimensions
http://real3d.pk
[/quote] Edited by luckyyyyyy

Share this post


Link to post
Share on other sites
WiredCat    1452
the func void T3DPlanet::GetOGLPos(int x, int y, t3dpoint & np, t3dpoint & fp)
[CODE]
void gluPerspectiveA(GLfloat fovy, GLfloat aspect, GLfloat zmin, GLfloat zmax)
{
GLfloat xmin, xmax, ymin, ymax;
ymax = zmin * tan(fovy * M_PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
glFrustum(xmin, xmax, ymin, ymax, zmin, zmax);
}
[/CODE]


provides the correct X and Y values for mouse cursor,

The idea of my soulition is: (i will explain the code now)
the idea is as follows:
set z near and z far closely
gluPerspectiveA(90.0f, DISPLAY_WIDTH/DISPLAY_HEIGHT,1000.0f, 2000.0f);
set the camera

then check nearest depth val and the farthest, then make from them a line and test whatever you want

gluUnProject(winX, winY, 0, modelview, projection, viewport, &nx, &ny, &nz); //the point on your screeen! (depth value 0,0f)
gluUnProject(winX, winY, 1, modelview, projection, viewport, &fx, &fy, &fz); //pushed far away point (depth value 1.0f)

Maybye you are not familiar with the dpeth values they are from 0 to 1 (depending on znear/zfar value 0.75 from depth vcan be farther than 0.75 from diffferent znear/zfar perspective ble ble ble ble )

[CODE]
void T3DPlanet::GetOGLPos(int x, int y[..])
{
[...]
glGetIntegerv( GL_VIEWPORT, viewport );
float winX = float(x);
float winY = float(viewport[3]) - float(y);

//optional readpixels

//optional one gluunproject(winx,winy, readpixeldepth, modelview, projection, viewport, outputx,outputy,outputz);
[/CODE]







if you do not want to make rays and then test some shit you use)
if you use glReadPixels() with the same x,y values (winX, winY) range 1 GL_DEPTH_COMPONENT (or GL_DEPTH_COMPONENT24)

after reading the depth value from the pixel you
call glunproject
heres is a pixel reading
[CODE]
void __fastcall READ_RGBA_FROM_OGL_WINDOW(int x,int height, int y, int & r, int & g, int & b, int & a)
{


unsigned char* pdata = new unsigned char[4];
glReadBuffer(GL_COLOR_BUFFER_BIT);

glReadPixels(x,height-y,1,1,GL_RGBA,GL_UNSIGNED_BYTE,pdata);

r = pdata[0];
g = pdata[1];
b = pdata[2];
a = pdata[3];
// delete B2;
delete [] pdata;
}

//so for depth is should be but i dont know if that is correct

float __fastcall READ_DEPTH_FROM_OGL_WINDOW(int x,int height, int y)
{

unsigned char* pdata = new unsigned char[1];
glReadBuffer(GL_DEPTH_BUFFER_BIT);
glReadPixels(x,height-y,1,1,GL_DEPTH_COMPONENT,GL_UNSIGNED_BYTE,pdata);

return float(pdata[0]) / 255.0f;

}

[/CODE]

[color=#ff0000][b]I have tried everything but not getting the exact X and Y values[/b][/color]. - no you didin't
[color=#ff0000][b]I am applying glPerspective() in real-time (display function) thats why [/b][/color]
- I don;t understand, you display the scene and you store for it a modelview matrix, projection matrix , and viewport
so you can call fcking gluUnProject

and do not use so big ratio between z_near/z_far


[b][color=#ff0000]I think I have to apply it with a specific matrix but i dont know which matrix.[/color][/b] - ah HELL NO !!!

[b][color=#ff0000]I do not want to select vertex or something like that I just need 3D coordinates at the click position.[/color][/b]


So WHA THE HELL ARE YOU WAITING FOR?
CLEAN YOUR CODE


and do as follows


draw the scene

store modelview matrix and stroe viewport also
(when want to click)
change perspective to 'nicest z_near/z_far aspect ratio)
store projection matrix
call gluUnProject and get the values

be happy ;(


I still have no idea what are you doing wrong dude Edited by ___

Share this post


Link to post
Share on other sites
luckyyyyyy    145
haha.. I like the way u teaching.. ;)

I got your point.. i do not want any kind of line intersection of whatever. I just want that when I click on model I get 3D coordinates.

I did what u said at the end. But didn't get this ?
(when want to click)
change perspective to 'nicest z_near/z_far aspect ratio)

now tell me where I am doing wrong?

[CODE]
void glPerspective()
{
glViewport(0, 0, WINDOW_SIZE_W, WINDOW_SIZE_H);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0, (GLdouble)WINDOW_SIZE_W / (GLdouble)WINDOW_SIZE_H, 0.1, 10000.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, m_zoom, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glPerspective();

glPushMatrix();
glTranslatef(screenX, 0.0, 0.0);
glTranslatef(0.0, screenY, 0.0);
glRotatef(spin_y, 1.0, 0.0, 0.0);
glRotatef(spin_x, 0.0, 1.0, 0.0);
glRotatef(spin_z, 0.0, 0.0, 1.0);
glGetDoublev( GL_MODELVIEW_MATRIX, OGLMmodelview );
glGetDoublev( GL_PROJECTION_MATRIX, OGLMprojection );
glGetIntegerv( GL_VIEWPORT, OGLMviewport );

Render_Triangular_model();
glPopMatrix();
glutSwapBuffers();
}
GLpoint GetOGLMousePos(GLint x, GLint y)
{
GLdouble winX = 0.0, winY = 0.0, winZ = 0.0;
GLdouble posX = 0.0, posY = 0.0, posZ = 0.0;
winX = (float)x;
winY = (float)OGLMviewport[3] - (float)y - 1; // invert winY so that down lowers value
glReadPixels( x, GLint(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
gluUnProject( winX, winY, winZ, OGLMmodelview, OGLMprojection, OGLMviewport, &posX, &posY, &posZ);
return GLpoint(posX, posY, posZ);
}
[/CODE]

[quote]
Think of Design with Dimensions
http://real3d.pk
[/quote] Edited by luckyyyyyy

Share this post


Link to post
Share on other sites
luckyyyyyy    145
Thanks for your precious time. Now its solved. I mention the problem below. Usually we used to ignore (float or double) variables during programming, I think we should not.

[CODE]
GLpoint GetOGLMousePos(GLint x, GLint y)
{
GLfloat winX = 0.0, winY = 0.0, winZ = 0.0; // never ever make a mistake between float and double.
I wasted my 4 days to solve this and the problem was, I was using GLdouble here instead of GLfloat.
Try GLdouble here you will see a hell difference in output values.


GLdouble posX = 0.0, posY = 0.0, posZ = 0.0;
winX = (float)x;
winY = (float)OGLMviewport[3] - (float)y; // invert winY so that down lowers value
glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );
gluUnProject( winX, winY, winZ, OGLMmodelview, OGLMprojection, OGLMviewport, &posX, &posY, &posZ);
return GLpoint(posX, posY, -posZ); // invert z value
}
[/CODE]

[quote]
Think of Design with Dimensions
[url="http://real3d.pk"]http://real3d.pk[/url]
[/quote] Edited by luckyyyyyy

Share this post


Link to post
Share on other sites
WiredCat    1452
Lol i have compiled your code and did the same with this double (changed to float) but still cant read the winZ lol ; ]
remember to read pixels only when you have depth buffer filled with this what you want to check, do ont call getoglpos whenever you want because t might not work Edited by ___

Share this post


Link to post
Share on other sites
luckyyyyyy    145
haha.. NO i dont have any issue now... working like charm..
thanks to u.



[quote]Think of Design with Dimensions
[url="http://real3d.pk"]http://real3d.pk[/url][/quote] Edited by luckyyyyyy

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Similar Content

    • By povilaslt2
      Hello. I'm Programmer who is in search of 2D game project who preferably uses OpenGL and C++. You can see my projects in GitHub. Project genre doesn't matter (except MMO's :D).
    • By ZeldaFan555
      Hello, My name is Matt. I am a programmer. I mostly use Java, but can use C++ and various other languages. I'm looking for someone to partner up with for random projects, preferably using OpenGL, though I'd be open to just about anything. If you're interested you can contact me on Skype or on here, thank you!
      Skype: Mangodoor408
    • By tyhender
      Hello, my name is Mark. I'm hobby programmer. 
      So recently,I thought that it's good idea to find people to create a full 3D engine. I'm looking for people experienced in scripting 3D shaders and implementing physics into engine(game)(we are going to use the React physics engine). 
      And,ye,no money =D I'm just looking for hobbyists that will be proud of their work. If engine(or game) will have financial succes,well,then maybe =D
      Sorry for late replies.
      I mostly give more information when people PM me,but this post is REALLY short,even for me =D
      So here's few more points:
      Engine will use openGL and SDL for graphics. It will use React3D physics library for physics simulation. Engine(most probably,atleast for the first part) won't have graphical fron-end,it will be a framework . I think final engine should be enough to set up an FPS in a couple of minutes. A bit about my self:
      I've been programming for 7 years total. I learned very slowly it as "secondary interesting thing" for like 3 years, but then began to script more seriously.  My primary language is C++,which we are going to use for the engine. Yes,I did 3D graphics with physics simulation before. No, my portfolio isn't very impressive. I'm working on that No,I wasn't employed officially. If anybody need to know more PM me. 
       
    • By Zaphyk
      I am developing my engine using the OpenGL 3.3 compatibility profile. It runs as expected on my NVIDIA card and on my Intel Card however when I tried it on an AMD setup it ran 3 times worse than on the other setups. Could this be a AMD driver thing or is this probably a problem with my OGL code? Could a different code standard create such bad performance?
    • By Kjell Andersson
      I'm trying to get some legacy OpenGL code to run with a shader pipeline,
      The legacy code uses glVertexPointer(), glColorPointer(), glNormalPointer() and glTexCoordPointer() to supply the vertex information.
      I know that it should be using setVertexAttribPointer() etc to clearly define the layout but that is not an option right now since the legacy code can't be modified to that extent.
      I've got a version 330 vertex shader to somewhat work:
      #version 330 uniform mat4 osg_ModelViewProjectionMatrix; uniform mat4 osg_ModelViewMatrix; layout(location = 0) in vec4 Vertex; layout(location = 2) in vec4 Normal; // Velocity layout(location = 3) in vec3 TexCoord; // TODO: is this the right layout location? out VertexData { vec4 color; vec3 velocity; float size; } VertexOut; void main(void) { vec4 p0 = Vertex; vec4 p1 = Vertex + vec4(Normal.x, Normal.y, Normal.z, 0.0f); vec3 velocity = (osg_ModelViewProjectionMatrix * p1 - osg_ModelViewProjectionMatrix * p0).xyz; VertexOut.velocity = velocity; VertexOut.size = TexCoord.y; gl_Position = osg_ModelViewMatrix * Vertex; } What works is the Vertex and Normal information that the legacy C++ OpenGL code seem to provide in layout location 0 and 2. This is fine.
      What I'm not getting to work is the TexCoord information that is supplied by a glTexCoordPointer() call in C++.
      Question:
      What layout location is the old standard pipeline using for glTexCoordPointer()? Or is this undefined?
       
      Side note: I'm trying to get an OpenSceneGraph 3.4.0 particle system to use custom vertex, geometry and fragment shaders for rendering the particles.
  • Popular Now