Jump to content

  • Log In with Google      Sign In   
  • Create Account


Incorrect 3D coordinates from 2D mouse click ?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 luckyyyyyy   Members   -  Reputation: 144

Like
0Likes
Like

Posted 07 October 2012 - 06:52 PM

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


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);
}

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

-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

Think of Design with Dimensions
http://real3d.pk


Edited by luckyyyyyy, 13 October 2012 - 07:13 AM.


Sponsor:

#2 MarkS   Prime Members   -  Reputation: 878

Like
0Likes
Like

Posted 08 October 2012 - 12:14 AM

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.

#3 WiredCat   Members   -  Reputation: 207

Like
0Likes
Like

Posted 08 October 2012 - 07:35 AM

hey dude first thing is your perspective calculation (the z near z far problem!)


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]


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 :/

http://www.youtube.com/watch?v=YAeedDLS7aE&feature=youtu.be

Edited by ___, 08 October 2012 - 07:38 AM.


#4 luckyyyyyy   Members   -  Reputation: 144

Like
0Likes
Like

Posted 09 October 2012 - 11:00 AM

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.


Think of Design with Dimensions
http://real3d.pk


Edited by luckyyyyyy, 13 October 2012 - 07:13 AM.


#5 WiredCat   Members   -  Reputation: 207

Like
0Likes
Like

Posted 10 October 2012 - 07:37 AM

the func void T3DPlanet::GetOGLPos(int x, int y, t3dpoint & np, t3dpoint & fp)
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);
}


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 )

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);







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
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;

}


I have tried everything but not getting the exact X and Y values. - no you didin't
I am applying glPerspective() in real-time (display function) thats why
- 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


I think I have to apply it with a specific matrix but i dont know which matrix. - ah HELL NO !!!

I do not want to select vertex or something like that I just need 3D coordinates at the click position.


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 ___, 10 October 2012 - 07:46 AM.


#6 luckyyyyyy   Members   -  Reputation: 144

Like
0Likes
Like

Posted 10 October 2012 - 11:45 PM

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?

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);
}

Think of Design with Dimensions
http://real3d.pk


Edited by luckyyyyyy, 13 October 2012 - 07:12 AM.


#7 WiredCat   Members   -  Reputation: 207

Like
0Likes
Like

Posted 11 October 2012 - 03:06 PM

i am having trouble with reading from depth buffer (reading the winZ) if i solve this i will post it, i think tommorow

#8 luckyyyyyy   Members   -  Reputation: 144

Like
0Likes
Like

Posted 12 October 2012 - 03:06 AM

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.

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
}

Think of Design with Dimensions
http://real3d.pk


Edited by luckyyyyyy, 13 October 2012 - 07:12 AM.


#9 WiredCat   Members   -  Reputation: 207

Like
0Likes
Like

Posted 12 October 2012 - 11:13 AM

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 ___, 12 October 2012 - 11:15 AM.


#10 luckyyyyyy   Members   -  Reputation: 144

Like
0Likes
Like

Posted 13 October 2012 - 10:28 AM

haha.. NO i dont have any issue now... working like charm..
thanks to u.



Think of Design with Dimensions
http://real3d.pk


Edited by luckyyyyyy, 13 October 2012 - 10:29 AM.





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS