+static gint run_picking(GritsOpenGL *opengl, GPtrArray *objects)
+{
+ /* Setup picking buffers */
+ guint buffer[100][4] = {};
+ glSelectBuffer(G_N_ELEMENTS(buffer), (guint*)buffer);
+ if (!opengl->pickmode)
+ glRenderMode(GL_SELECT);
+ glInitNames();
+
+ /* Render/pick objects */
+ for (guint i = 0; i < objects->len; i++) {
+ glPushName(i);
+ GritsObject *object = objects->pdata[i];
+ object->state.picked = FALSE;
+ grits_object_pick(object, opengl);
+ glPopName();
+ }
+
+ int hits = glRenderMode(GL_RENDER);
+
+ /* Process hits */
+ for (int i = 0; i < hits; i++) {
+ //g_debug("\tHit: %d", i);
+ //g_debug("\t\tcount: %d", buffer[i][0]);
+ //g_debug("\t\tz1: %f", (float)buffer[i][1]/0x7fffffff);
+ //g_debug("\t\tz2: %f", (float)buffer[i][2]/0x7fffffff);
+ //g_debug("\t\tname: %p", (gpointer)buffer[i][3]);
+ guint index = buffer[i][3];
+ GritsObject *object = objects->pdata[index];
+ object->state.picked = TRUE;
+ }
+
+ /* Notify objects of pointer movements */
+ for (guint i = 0; i < objects->len; i++) {
+ GritsObject *object = objects->pdata[i];
+ grits_object_set_pointer(object, object->state.picked);
+ }
+
+ return hits;
+}
+
+static gboolean on_motion_notify(GritsOpenGL *opengl, GdkEventMotion *event, gpointer _)
+{
+ gdouble height = GTK_WIDGET(opengl)->allocation.height;
+ gdouble gl_x = event->x;
+ gdouble gl_y = height - event->y;
+ gdouble delta = opengl->pickmode ? 200 : 2;
+
+ if (opengl->pickmode) {
+ gtk_gl_begin(GTK_WIDGET(opengl));
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
+
+ /* Save matricies */
+ gdouble projection[16];
+ gint viewport[4]; // x=0,y=0,w,h
+ glGetDoublev(GL_PROJECTION_MATRIX, projection);
+ glGetIntegerv(GL_VIEWPORT, viewport);
+ glMatrixMode(GL_MODELVIEW); glPushMatrix();
+ glMatrixMode(GL_PROJECTION); glPushMatrix();
+
+ g_mutex_lock(opengl->objects_lock);
+
+ GPtrArray *ortho = _objects_to_array(opengl, TRUE);
+ GPtrArray *world = _objects_to_array(opengl, FALSE);
+
+ /* Run perspective picking */
+ glMatrixMode(GL_PROJECTION); glLoadIdentity();
+ gluPickMatrix(gl_x, gl_y, delta, delta, viewport);
+ glMultMatrixd(projection);
+ gint world_hits = run_picking(opengl, world);
+
+ /* Run ortho picking */
+ glMatrixMode(GL_PROJECTION); glLoadIdentity();
+ gluPickMatrix(gl_x, gl_y, delta, delta, viewport);
+ glMatrixMode(GL_MODELVIEW); glLoadIdentity();
+ glOrtho(0, viewport[2], viewport[3], 0, 1000, -1000);
+ gint ortho_hits = run_picking(opengl, ortho);
+
+ g_debug("GritsOpenGL: on_motion_notify - hits=%d/%d,%d/%d ev=%.0lf,%.0lf",
+ world_hits, world->len, ortho_hits, ortho->len, gl_x, gl_y);
+
+ g_ptr_array_free(world, TRUE);
+ g_ptr_array_free(ortho, 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();
+ glMatrixMode(GL_MODELVIEW); glPopMatrix();
+
+ if (opengl->pickmode)
+ gtk_gl_end(GTK_WIDGET(opengl));
+
+ return FALSE;
+}
+