PDA

View Full Version : Get world coordinate



trackin
04-28-2012, 05:44 AM
Hi guys,
I create my point cloud viewer and now i'm trying to implement mouse points picking. I find a lot of tutorials about this issue but i have some problems.
i draw on the screen my point cloud by:



GLsizei vx, vy;
vx = glutGet( GLUT_WINDOW_WIDTH );
vy = glutGet( GLUT_WINDOW_HEIGHT );
double aspect = double(vx)/double(vy);


glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective( 45*zoomFactor, aspect, 1, 100. );


glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt ( 0, 0, 10., 0., 0., 0., 0., 1., 0. );
glMultMatrixf(matrix);
glPointSize(3.0);
glBegin(GL_POINTS);
for(int i = 0; i < content->nvertex; i++){
glVertex3f(content->vertexes[i].x, content->vertexes[i].y, content->vertexes[i].z);
}
glEnd();
glutSwapBuffers();
glFlush();

where matrix is a rotation matrix calculate by trackball.
When I click on the screen I'm able to get (x,y) screen coordinate and then i want get 3D world-coordinate by:

GLdouble sx, sy, sz; GLdouble ex, ey, ez;


GLint viewport[4];
GLdouble modelview[16];
GLdouble projection[16];


GLsizei vx, vy;
vx = glutGet( GLUT_WINDOW_WIDTH );
vy = glutGet( GLUT_WINDOW_HEIGHT );
double aspect = double(vx)/double(vy);


glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45*zoomFactor, aspect, 1, 100. );


glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
gluLookAt ( 0, 0, 10., 0., 0., 0., 0., 1., 0. );


glMultMatrixf(matrix);
GLint realy;
glGetIntegerv(GL_VIEWPORT,viewport);
glGetDoublev(GL_MODELVIEW_MATRIX,modelview);
glGetDoublev(GL_PROJECTION_MATRIX,projection);


realy = viewport[3] - y;//viewport[3] - y;
gluUnProject( (double) x, realy, 0.0, // Near
modelview, projection, viewport,
&sx, &sy, &sz );


cout << sx << ", " << sy<< ", " << sz<< ", " << endl;
gluUnProject( (double) x, realy, 1.0f, // Far
modelview, projection, viewport,
&ex, &ey, &ez );

and I pick a point by ray tracing.
I create a simple example where a set of points (1,0,0) (2,0,0) (3,0,0) (4,0,0) ... (10,0,0) are drawn on the screen but i can pick the point only if i move the mouse between first point and second one. If I rotate this points by trackball i have similar problem. I'm not to be able to find a solution. I search on google for long times but nothing help me to solve this problem.
Please help me!!

bye

G.

tonyo_au
04-28-2012, 07:21 PM
This is just a personal opinion but when I got serious about picking a point on the screen and needing to know the exact world coordinate I abandoned gluUnProject and created an extra render buffer that records the world coordinate in the fragment shader.
Now I don't have any trouble (and it is super fast) for the cost of a little graphics memory.

trackin
04-29-2012, 03:37 AM
This is just a personal opinion but when I got serious about picking a point on the screen and needing to know the exact world coordinate I abandoned gluUnProject and created an extra render buffer that records the world coordinate in the fragment shader.
Now I don't have any trouble (and it is super fast) for the cost of a little graphics memory.

can you post an example? I have problem to get 3D coordinate from 2D screen coordinate. How can extra buffer solve my problem?

Cheers

G.

tonyo_au
04-29-2012, 06:33 PM
First, so I don't make too many assumptions. Do you know how to create a frame buffer object (FBO) with multi-rendering?

If you do, then something like this code in the fragment shader will record the world corrdinate to the render buffer. (Please note this is not necessarily
the most efficient code).



float near = u_NearFar.x;
float far = u_NearFar.y;
float diff = far - near;
float sum = far + near;
float q = -sum/diff;
float qn = -2*near*far/diff;

// convert window to ndc
vec3 ndc = vec3(gl_FragCoord.xy / u_Screen.xy,gl_FragCoord.z);
ndc = ndc * 2.0f - 1.0f;
// convert window Z to clip z
// NOTE frag.w = 1/w clip
vec3 clip = ndc / gl_FragCoord.w;
// convert clip z to eye z
float ze = gl_FragCoord.z / gl_FragCoord.w;
// convert clip x,y to eye x,y
vec2 xye = clip.xy / vec2(u_CameraProjection[0].x,u_CameraProjection[1].y);
// convert from eye space to world
vec4 worldSpace = u_CameraViewInvert * vec4(xye,-ze,1.0f);
worldSpace.w = ze;
Fragout_location = worldSpace;


The main advantage of recording something in the fragment shader is that the value z is still in 32-bit precision whereas the depth buffer is often 24-bit.
Just recording the z value in a float texture buffer and doing the screen to world logic in the pick code on the cpu will also work and is probably faster.

trackin
04-30-2012, 05:52 AM
hi tonyo,
thank you for your help.
I haven't used FBO yet. I don't understand your code and what the variables represent (e.g.
u_NearFar, gl_FragCoord,
u_Screen etc....)!
can you explaine your code??

thanks!

G.