From 64cd64653195ced67f25f6b8560953f420c0746c Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Mon, 6 Feb 2012 06:32:35 +0000 Subject: [PATCH] Add grits_viewer_unproject function This does the opposite of the grits_viewer_project function and can be used to get the lat-lon-elev point corresponding to a point on the screen, such as the pointer location. This currently has an undefined output if the screen coordinates do not map to the location of an object in the viewer. This should not be used to determine if an objects has been selected or clicked on. OpenGL picking should be used for that by connecting to one of the GritsObject mouse event signals. --- src/grits-opengl.c | 30 ++++++++++++++++++++++++++++++ src/grits-viewer.c | 29 +++++++++++++++++++++++++++-- src/grits-viewer.h | 6 ++++++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/src/grits-opengl.c b/src/grits-opengl.c index 961a875..3d7b7dd 100644 --- a/src/grits-opengl.c +++ b/src/grits-opengl.c @@ -316,6 +316,11 @@ static gboolean on_motion_notify(GritsOpenGL *opengl, GdkEventMotion *event, gpo g_ptr_array_free(objects, TRUE); g_mutex_unlock(opengl->objects_lock); + /* Test unproject */ + gdouble lat, lon, elev; + grits_viewer_unproject(GRITS_VIEWER(opengl), + gl_x, gl_y, -1, &lat, &lon, &elev); + /* Cleanup */ glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -459,6 +464,30 @@ static void grits_opengl_project(GritsViewer *_opengl, px, py, pz); } +static void grits_opengl_unproject(GritsViewer *_opengl, + gdouble px, gdouble py, gdouble pz, + gdouble *lat, gdouble *lon, gdouble *elev) +{ + GritsOpenGL *opengl = GRITS_OPENGL(_opengl); + gdouble x, y, z; + if (pz < 0) { + gfloat tmp = 0; + glReadPixels(px, py, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &tmp); + pz = tmp; + } + gluUnProject(px, py, pz, + opengl->sphere->view->model, + opengl->sphere->view->proj, + opengl->sphere->view->view, + &x, &y, &z); + xyz2lle(x, y, z, lat, lon, elev); + //g_message("GritsOpenGL: unproject - " + // "%4.0lf,%4.0lf,(%5.3lf) -> " + // "%8.0lf,%8.0lf,%8.0lf -> " + // "%6.2lf,%7.2lf,%4.0lf", + // px, py, pz, x, y, z, *lat, *lon, *elev); +} + static void grits_opengl_set_height_func(GritsViewer *_opengl, GritsBounds *bounds, RoamHeightFunc height_func, gpointer user_data, gboolean update) { @@ -615,6 +644,7 @@ static void grits_opengl_class_init(GritsOpenGLClass *klass) GritsViewerClass *viewer_class = GRITS_VIEWER_CLASS(klass); viewer_class->center_position = grits_opengl_center_position; viewer_class->project = grits_opengl_project; + viewer_class->unproject = grits_opengl_unproject; viewer_class->clear_height_func = grits_opengl_clear_height_func; viewer_class->set_height_func = grits_opengl_set_height_func; viewer_class->add = grits_opengl_add; diff --git a/src/grits-viewer.c b/src/grits-viewer.c index 08d73bb..d9e2887 100644 --- a/src/grits-viewer.c +++ b/src/grits-viewer.c @@ -445,8 +445,8 @@ void grits_viewer_center_position(GritsViewer *viewer, * grits_viewer_project: * @viewer: the viewer * @lat: the latitude - * @lon: the latitude - * @elev: the latitude + * @lon: the longitude + * @elev: the elevation * @px: the project x coordinate * @py: the project y coordinate * @pz: the project z coordinate @@ -465,6 +465,31 @@ void grits_viewer_project(GritsViewer *viewer, klass->project(viewer, lat, lon, elev, px, py, pz); } +/** + * grits_viewer_unproject: + * @viewer: the viewer + * @x: x coordinate in screen space + * @y: y coordinate in screen space + * @z: z coordinate in screen space, or -1 to use the value + * from the depth buffer at x and y as the z value + * @lat: the latitude + * @lon: the longitude + * @elev: the elevation + * + * Project a x, y point in screen space to a latitude, longitude, and elevation + * point. Useful for finding the position of the cursor or another on-screen + * object in world coordinates. + */ +void grits_viewer_unproject(GritsViewer *viewer, + gdouble px, gdouble py, gdouble pz, + gdouble *lat, gdouble *lon, gdouble *elev) +{ + GritsViewerClass *klass = GRITS_VIEWER_GET_CLASS(viewer); + if (!klass->unproject) + g_warning("GritsViewer: unproject - Unimplemented"); + klass->unproject(viewer, px, py, pz, lat, lon, elev); +} + /** * grits_viewer_clear_height_func: * @viewer: the viewer diff --git a/src/grits-viewer.h b/src/grits-viewer.h index 15d9d70..8991cb5 100644 --- a/src/grits-viewer.h +++ b/src/grits-viewer.h @@ -131,6 +131,9 @@ struct _GritsViewerClass { void (*project) (GritsViewer *viewer, gdouble lat, gdouble lon, gdouble elev, gdouble *px, gdouble *py, gdouble *pz); + void (*unproject) (GritsViewer *viewer, + gdouble px, gdouble py,gdouble pz, + gdouble *lat, gdouble *lon, gdouble *elev); void (*clear_height_func)(GritsViewer *viewer); void (*set_height_func) (GritsViewer *viewer, GritsBounds *bounds, @@ -171,6 +174,9 @@ void grits_viewer_center_position(GritsViewer *viewer, void grits_viewer_project(GritsViewer *viewer, gdouble lat, gdouble lon, gdouble elev, gdouble *px, gdouble *py, gdouble *pz); +void grits_viewer_unproject(GritsViewer *viewer, + gdouble px, gdouble py, gdouble pz, + gdouble *lat, gdouble *lon, gdouble *elev); void grits_viewer_clear_height_func(GritsViewer *viewer); void grits_viewer_set_height_func(GritsViewer *viewer, GritsBounds *bounds, -- 2.43.2