Sign in to follow this  

[RESOLVED] gluUnproject headaches

This topic is 3809 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I got me a scene which essentially consists of a perspective-viewed flat plane along which objects are dispersed in a random fashion. There is nothing between these objects. The plane is the xy-plane and I view it along the z axis from a camera with arbitrary coordinates. I want to be able to pick objects with the mouse and do stuff to them. So I try to use gluUnproject, but it keeps giving me the wrong coordinates. Nothing I've tried works. The code is below; any ideas what might be wrong?
void Session::SelectSystem(int x, int y){
	static GLdouble modelmatrix[16];
	static GLdouble projmatrix[16];
	static GLint viewport[4];

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

	GLdouble tx, ty, tz;
	GLdouble z;
	glReadPixels(x, viewport[3]-y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);

	gluUnProject(x, y, z, modelmatrix, projmatrix, viewport, &tx, &ty, &tz);
}
[Edited by - Hnefi on July 8, 2007 1:05:53 PM]

Share this post


Link to post
Share on other sites
Your code is perfectly fine. Are you rendering in wireframe mode? Are you making sure to call SelectSystem after everything is rendered to the screen? If the depth buffer is blank then you'll definitely get odd values.

Share this post


Link to post
Share on other sites
Hmm. I'm using SDL and SelectSystem is triggered during a mouseclick event. It's possible that this event is triggered before the render loop. I'll try to synch it and see what happens. ETA: Synching it didn't work. Placed the code directly after I finished rendering the world and got identical result.

Is there otherwise a way to unproject screen coordinates to a plane, parallell to the camera and a given distance from it without doing the linear algebra manually?

Share this post


Link to post
Share on other sites
To be honest, I've never gotten this to work with glReadPixels() either. It always threw weird numbers at me, no matter what I did. But there is another way - you can call gluUnProject() twice, with z-coords of 0 and 1. You can then construct a ray (well, a line segment really) between the two points and collide this ray with your geometry (and if there are no collisions, I find the intersection with the y=0 plane). This works fine, assuming this isn't some issue with SDL. I can post some code if you like (it's a bit long and in Java).

Share this post


Link to post
Share on other sites
That might work. Beats projecting everything onto the screen, anyway.

As far as I understand, the "z" coordinate in gluUnProject is the normalized z-buffer. Does that mean that with a viewport that goes from 1 to 1000 in the z direction, a z=0 means, in world coordinates relative to the camera, world_z = 1 and z=1 => world_z = 1000?

Share this post


Link to post
Share on other sites
Quote:
Original post by Hnefi
That might work. Beats projecting everything onto the screen, anyway.

As far as I understand, the "z" coordinate in gluUnProject is the normalized z-buffer. Does that mean that with a viewport that goes from 1 to 1000 in the z direction, a z=0 means, in world coordinates relative to the camera, world_z = 1 and z=1 => world_z = 1000?


Exactly, it goes between the near and far plane. The difference of the results is the direction of the ray (in camera space, if I'm not mistaken), and the origin is at the camera.

Share this post


Link to post
Share on other sites
Success! The final code (before cleanup, obviously) ended up looking like this, with the result of the mouse coordinates in z = 0 being stored in rx and ry:
void Session::SelectSystem(int x, int y){
static GLdouble modelmatrix[16];
static GLdouble projmatrix[16];
static GLint viewport[4];

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

static GLdouble x1, y1, z1, x2, y2, z2, rx, ry;

gluUnProject(x, viewport[3]-y, 0, modelmatrix, projmatrix, viewport, &x1, &y1, &z1);
gluUnProject(x, viewport[3]-y, 1, modelmatrix, projmatrix, viewport, &x2, &y2, &z2);

z1 -= screen->camera->GetPos().z;
x1 -= screen->camera->GetPos().x;
y1 += screen->camera->GetPos().y;
double t = z2/z1;
rx = x2 - x1*t;
ry = y2 - y1*t;
if(z2 - z1*t > 0.01 || z2 - z1*t < -0.01)
Error(true, 0, "Crud!");
}

The viewport[3]-y is most likely due to the fact that I translate my camera thusly:
void Camera::Translate() const{
glTranslated(-pos.x, pos.y, -pos.z);
}


So there we go. Finally a working unproject. Thanks for all your help guys!

Share this post


Link to post
Share on other sites

This topic is 3809 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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