gluProject and gluUnProject problems

I’m trying to use the code below for converting screen coordinates to 3D and vice versa, but the results are completely wrong (insanely random values). The code samples are straight from glu manuals and other tutorials and seem logical. I’m probably doing a very basic implementation error related to openframeworks but can’t figure it out (i’ve tried normalizing the 2D coordinates or multiplying the results by ofGetWidth() ofGetHeight() etc. but to no avail). Anyone have any ideas?

2D mouse coordinates -> 3D

  
  
float mouse3D[3];	  
  
void calcMouse3D() {  
	GLdouble modelview[16], projection[16];  
    GLint viewport[4];  
    GLfloat z;  
	//get the projection matrix		  
    glGetDoublev( GL_PROJECTION_MATRIX, projection );  
	//get the modelview matrix		  
    glGetDoublev( GL_MODELVIEW_MATRIX, modelview );  
	//get the viewport		  
    glGetIntegerv( GL_VIEWPORT, viewport );  
	  
    //Read the window z co-ordinate   
    //(the z value on that point in unit cube)		  
    glReadPixels( mouseX, viewport[3] - mouseY, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z );  
	  
    //Unproject the window co-ordinates to   
    //find the world co-ordinates.  
    gluUnProject( mouseX, viewport[3] - mouseY, z, modelview, projection, viewport, (GLdouble *)mouse3D, (GLdouble *)(mouse3D+1), (GLdouble *)(mouse3D+2) );  
}  
  

and 3D -> 2D

  
  
	GLdouble ret_x, ret_y, ret_z;  
	  
	// arrays to hold matrix information  
	GLdouble model_view[16];  
	glGetDoublev(GL_MODELVIEW_MATRIX, model_view);  
	  
	GLdouble projection[16];  
	glGetDoublev(GL_PROJECTION_MATRIX, projection);  
	  
	GLint viewport[4];  
	glGetIntegerv(GL_VIEWPORT, viewport);  
	  
	// get 3D coordinates based on window coordinates  
	  
	gluProject(x, y, z, model_view, projection, viewport, &ret_x, &ret_y, &ret_z);  
  

usually problems with these functions come down to your z position. Try playing with that value until you hone in on reasonable results.

Hi,

Im now specifically trying the mouse -> 3D (the first chunk of code). How can I play with the Z values? I have a few 3D objects in the scene, and i’m moving my mouse around the window printing the output of the calcMouse3D() function. I’m expecting to get weird results when I’m not hoving over any 3D object, but I should get reasonable results when the mouse is over a 3D object. But instead I’m just getting completely random values, insanely large. And not related to whether my mouse is over an object or not :S

Any luck on this one? I’m struggling with this too.

nope, i found no solution and shortly after posting this, I gave up, moved on, and haven’t revisited the situation since. If you do find the answer please lemme know!

well I did not really try it but it would be useful. In theory it should not be too hard but I guess this is a good example that practice and theory are sometimes far away from each other. I will give this a try in my spare time.

ohh man not sure about this. Tried a bunch of examples I found online but no go. Theo showed me some stuff here did to export 3d graphics using gluUnProject(…) He is the guy to answer this :slight_smile:

update:
just tried this and worked:

like memo said:

  
  
 GLdouble ret_x, ret_y, ret_z;  
     
   // arrays to hold matrix information  
   GLdouble model_view[16];  
   glGetDoublev(GL_MODELVIEW_MATRIX, model_view);  
     
   GLdouble projection[16];  
   glGetDoublev(GL_PROJECTION_MATRIX, projection);  
     
   GLint viewport[4];  
   glGetIntegerv(GL_VIEWPORT, viewport);  
     
   // get 3D coordinates based on window coordinates  
     
   gluProject(x, y, z, model_view, projection, viewport, &ret_x, &ret_y, &ret_z);   

then to fix the y value

  
ofPoint(ret_x, ofGetHeight()-ret_y);  
  

T
[/code]

does anyone know how to do this if you are rotating in XYZ. Like a rectangle drawn with ofVertex.

  
      
    ofVertex(x2, y1);  
    ofVertex(x2, y1);  
    ofVertex(x2, y2);  
    ofVertex(x2, y2);  
  

and then to rotate it in 3d

  
      
glRotatef(x, y, z);  
    ofVertex(x2, y1);  
    ofVertex(x2, y1);  
    ofVertex(x2, y2);  
    ofVertex(x2, y2)  
  

I messed around with these functions the other day. The reason they swing so wildly is due to the nonlinear map of zbuffer values [0, 1] to actual 3D space. As an example, in gluUnProject, a z input of 0 will give you a 3D point on the near clipping plane a z input of 1 will give you a 3D point on the far clipping plane. If your clipping planes are from [0.1, 100], a z value of 0.9 will give you a 3D point in the range of [3, 6] units from your near clipping plane (or something around there).

What I’ve been doing with 2D->3D projections is

  1. get the 3D point on the near and far clipping planes,
  2. make a ray from the near to far point
  3. cast the ray into the scene to figure out what the user is clicking on

hmmm,
I have no problem with getting a 2d point from a 3d point using what memo posted ofGetScreenXYZ()… The only thing that I had to change is for Y because in OF y is at the botom so return y-ofGetHeight() worked.

What I want to figure out is how to get the 2d position of a 3d point that is also rotating in 3d space like:

normally like this (3d)

  
glPushMatrix();  
glTransaltef(pos.x, pos.y, pos.z);  
glRotatef(rot.x, rot.y, rot.z);  
  
//draw something  
  
glPopMatrix();  

now I need to find the 2d equivalent of rot and pos

To go from 3d->2d, you need to do the perspective divide on your 3D points.

In shader code, this is what I do to go from model coordinates to normalized screen coordinates:

vec4 p = gl_ModelViewProjectionMatrix*vec4(gl_Vertex, 1.);
vec2 s = 0.5*(p.xy/p.w+1.); // perspective divide and convert form [-1, 1] -> [0, 1]

For 2d->3d, try doing the following during setup.

  
glEnable( GL_DEPTH_TEST );  
glDepthMask(1);  
glDepthFunc( GL_LEQUAL );   

hi all,
i’m trying to run the 2D to 3D code for every pixel on the image to create a grayscale depth map of the 3dmodel.
http://forum.openframeworks.cc/t/displaying-z-buffer/6199/0

would you recommend a fast way of doing this?
a 100x100px zone is too slow to update for every frame and i would like to do it for the whole window.
of would you recommend some other way?

thank you all!

  
  
float xyz[w*h];  
int i = 0;  
for (int x = 0; x <= w; x++) {  
	for (int y = 0; y <= h; y++) {  
		  
		GLdouble modelview[16], projection[16];  
		GLint viewport[4];  
		GLfloat z;  
  
		//get the projection matrix		  
		glGetDoublev( GL_PROJECTION_MATRIX, projection );  
		//get the modelview matrix		  
		glGetDoublev( GL_MODELVIEW_MATRIX, modelview );  
		//get the viewport		  
		 glGetIntegerv( GL_VIEWPORT, viewport );  
		  
		 //Read the window z co-ordinate   
		//(the z value on that point in unit cube)		  
		glReadPixels( mouseX, mouseY, z, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z );  
		  
		 //Unproject the window co-ordinates to   
		 //find the world co-ordinates.  
  
		gluUnProject( x, y, z, modelview, projection, viewport, (GLdouble *)xyz, (GLdouble *)(xyz+1), (GLdouble *)(xyz+2));  
		  
		zdepth[i]=xyz[3];  
		i++;  
  
		maxz = max(xyz[3],maxz); //used later to scale values from 0 to 255  
		minz = max(xyz[3],minz);  
	}  
}  
  

Hello, iam trying the same but

glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev (GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev (GL_PROJECTION_MATRIX, projmatrix);

give me random numbers in matrices. Why?

I was doing in Objective-C and had the same problem.
This worked to me:

-(MPoint*) to2DPointFrom3DPoint: (MPoint*)point3D {
    double wx, wy, wz;
    --->>> [[self openGLContext] makeCurrentContext]; <<<---
    GLdouble model_view[16];
    glGetDoublev(GL_MODELVIEW_MATRIX, model_view);
    GLdouble projection[16];
    glGetDoublev(GL_PROJECTION_MATRIX, projection);
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);
    gluProject(point3D.x, point3D.y, point3D.z, model_view, projection, viewport, &wx, &wy, &wz);
    wy = viewport[3] - wy;
    MPoint* point2D = [[MPoint alloc] initWithX:wx Y:wy Z:wz];
    return point2D;
}