Results 1 to 7 of 7

Thread: What is the best method for object picking?

  1. #1
    Member Newbie
    Join Date
    Jul 2008
    Posts
    40

    What is the best method for object picking?

    Hi

    If I turn to Chapter 13 of the Red Book [7th ed.] it states at the start of the chapter that from OpenGL v3.1 all of the selection and picking techniques described in the chapter have been dumped.

    Thus, what is the best method of picking an object?

    Does the statement at the start of Chapter 13 mean that if I a use a GL version less than 3.1 I use the methods described and 3.1+ I use another method, or should I be using a different method for all versions?

    Also, I'm using JOGL and are there established classes [as there are for trackball] for object selection and picking or do I have to reinvent the wheel?

    Thanks

    Graham

  2. #2
    V-man
    Guest

    Re: What is the best method for object picking?


  3. #3
    Member Newbie
    Join Date
    Jul 2008
    Posts
    40

    Re: What is the best method for object picking?

    Hi

    Thanks for the reply. Your opengl.org link seems to suggest using glReadPixels() or using a ray-tracing method.

    I see you had a link to glhlib, which appears a C++ lib. However, I'm using JOGL.

    Thanks

  4. #4
    V-man
    Guest

    Re: What is the best method for object picking?

    Quote Originally Posted by gmseed
    Hi

    Thanks for the reply. Your opengl.org link seems to suggest using glReadPixels() or using a ray-tracing method.

    I see you had a link to glhlib, which appears a C++ lib. However, I'm using JOGL.

    Thanks
    That's correct, use glReadPixels() for color picking or use a ray-tracing method.

    You don't need glhlib. That's just my signature.
    Although, my lib has a function for ray to triangle testing.

  5. #5
    Member Newbie
    Join Date
    Jul 2008
    Posts
    40

    Re: What is the best method for object picking?

    Here's my attempt at the pick-ray method described at:

    http://www.opengl.org/resources/faq/.../selection.htm

    However, there's a bug in it somewhere as is doesn't draw a pick-ray correctly.

    Graham
    ===


    public Ray3D mouseRayWorldCoordinates(GLAutoDrawable drawable)
    {
    // http://www.java-tips.org/other-api-t...t-in-jogl.html
    GL2 gl2 = drawable.getGL().getGL2();

    int viewport[] = new int[4];
    float mvmatrix[] = new float[16];
    float projmatrix[] = new float[16];
    float wcoordNear[] = new float[4];
    float wcoordFar[] = new float[4];

    int x = xCoord;
    int y = yCoord;

    gl2.glGetIntegerv(GL2.GL_VIEWPORT, viewport, 0);
    gl2.glGetFloatv(GL2.GL_MODELVIEW_MATRIX, mvmatrix, 0);
    gl2.glGetFloatv(GL2.GL_PROJECTION_MATRIX, projmatrix, 0);
    int realy = viewport[3] - (int)y; /* GL y coord pos - note viewport[3] is height of window in pixels */

    // world near
    System.out.println("Coordinates at cursor are (" + x + ", " + realy);
    boolean ok = glu.gluUnProject((float) x, (float)realy, 0.0f, //
    mvmatrix, 0,
    projmatrix, 0,
    viewport, 0,
    wcoordNear, 0);
    System.out.println("World coords at z=0.0 are ( " //
    + wcoordNear[0] + ", " + wcoordNear[1] + ", " + wcoordNear[2]
    + "); ok: " + ok);
    // world far
    ok = glu.gluUnProject((float) x, (float) realy, 1.0f, //
    mvmatrix, 0,
    projmatrix, 0,
    viewport, 0,
    wcoordFar, 0);
    System.out.println("World coords at z=1.0 are (" //
    + wcoordFar[0] + ", " + wcoordFar[1] + ", " + wcoordFar[2]
    + "); ok: " + ok);

    // direction vector is far point - near point
    Vector3D dirVector = new Vector3D(wcoordFar[0]-wcoordNear[0],wcoordFar[1]-wcoordNear[1],wcoordFar[2]-wcoordNear[2]);
    dirVector.normalise();
    Point3D viewerLocation = GLUtilities.cameraLocation(drawable.getGL());
    Ray3D mouseRay = new Ray3D(viewerLocation,dirVector);

    return mouseRay;
    }

  6. #6

    Re: What is the best method for object picking?

    I've been putting together a data visualizer, and had to implement picking. I've had good success with using query objects. Here's a banged-together code snippet of all the pieces that I needed to get everything to work:

    Code :
    // Code to show how to use object queries to get picking behavior. For this code to work,
    // You'll need to add your preferred rendering framework. This code was pulled from an
    // FLTK framework I've been building for data visualization
     
    // Class-wide global variables here for the sake of a compact file
    // Classes that are not part of the OpenGl library are from the OpenGl SuperBible, 
    // which I highly reccomend: [url]http://www.starstonesoftware.com/OpenGL/[/url]
     
    GLMatrixStack       modelViewMatrix; 
    GLMatrixStack       projectionMatrix;
    GLFrustum           viewFrustum;
    bool 		    isPicking;
     
    // Constructor. Set up picking and the projection and model matrices
    PickingExample::PickingExample(int x,int y,int w,int h,const char *l)
                : Fl_Gl_Window(x,y,w,h,l)
    {
    	isPicking = false;
    	pickQueryResult = READY;
    	glGenQueries(1, &pickQueryID);
    	if(pickQueryID == 0){
    		pickQueryResult = PICK_ERROR;
    	}
     
    	viewFrustum.SetPerspective(45.0f, (float)screenWidth/(float)screenHeight, 0.5f, 1000.0f);
     
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    	modelViewMatrix.LoadIdentity();
    }
     
    // A slightly modified version of the original gluPickMatrix, taken from:
    // [url]http://oss.sgi.com/cgi-bin/cvsweb.cgi/projects/ogl-sample/main/gfx/lib/glu/libutil/project.c?rev=1.4;content-type=text%2Fplain[/url]
    void PickingExample::setPickMatrix(GLdouble x, GLdouble y, GLdouble deltax, GLdouble deltay, GLint viewport[4])
    {
     
        if (deltax <= 0 || deltay <= 0) { 
    		return;
        }
     
    	projectionMatrix.LoadIdentity();
     
    	/* Translate and scale the picked region to the entire window */
    	GLfloat dx = (float)((viewport[2] - 2 * (x - viewport[0])) / deltax);
    	GLfloat dy = (float)((viewport[3] - 2 * (y - viewport[1])) / deltay);
    	projectionMatrix.Translate(dx, dy, 0);
    	projectionMatrix.Scale((float)(viewport[2] / deltax), (float)(viewport[3] / deltay), 1.0);
     
    	projectionMatrix.MultMatrix(viewFrustum.GetProjectionMatrix());
    }
     
     
    // the main drawing method. In this case, only drawing for picking is done, though it would 
    // be easy enough to glClear() afther the picking code, and draw everything  over again with 
    // a normal perspective
    void PickingExample::draw() {
    	GLint result;
    	GLint viewport[4];
    	glGetIntegerv(GL_VIEWPORT,viewport);
     
    	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
     
     
    	modelViewMatrix.PushMatrix();
     
    		// Have some Euler angle rotations and translations just to show how 
    		// setPickMatrix() doesn't care about eye or model position
     
    		// global eye transformations	
    		modelViewMatrix.Rotate(eyeOrient[1], 0, 1, 0);
    		modelViewMatrix.Rotate(eyeOrient[0], 1, 0, 0);	
    		modelViewMatrix.Translate(eyePos[0], eyePos[1], eyePos[2]);
     
    		// global world transformations
    		modelViewMatrix.Translate(worldPos[0], worldPos[1], worldPos[2]);
    		modelViewMatrix.Rotate(worldOrient[0], 1, 0, 0);
    		modelViewMatrix.Rotate(worldOrient[1], 0, 1, 0);
     
    		// set up picking
    		if(isPicking &amp;&amp; (pickQueryResult != PICK_ERROR))
    			projectionMatrix.PushMatrix();
    				// set the projection matrix so that it's just looking at a (in this case) 10x10 pixel area 
    				// near the cursor. This method (shown above)
    				setPickMatrix(mouseX,viewport[3]-mouseY,10,10,viewport); 
     
    				// for each item that you want to test, bracket it with a glBeginQuery()/glEndQuery()
    				// You'll need a unique pickQueryID for each model
    				glBeginQuery(GL_ANY_SAMPLES_PASSED, pickQueryID);
     
    				// render your model associated with pickQueryID here. It is assumed that
    				// the projection matrix and the model matrix will be handled by your shader(s)
     
    				// finish the query for this particular model
    				glEndQuery(GL_ANY_SAMPLES_PASSED);
     
    			projectionMatrix.PopMatrix();
     
    			// For each item that you queried above, see if at least one pixel was drawn
    			// Again, you'll need a unique pickQueryID for each model
    			glGetQueryObjectiv(pickQueryID, GL_QUERY_RESULT, &amp;result);
    			if(result)
    				printf("hit\n");
    			else
    				printf("miss\n");
     
    			isPicking = false;
    		}
    	modelViewMatrix.PopMatrix();
    }

  7. #7
    Junior Member Newbie
    Join Date
    Apr 2012
    Posts
    1

    Re: What is the best method for object picking?

    The previous algorithm doesn't seem to take in account the depth test. (GL_SAMPLES_PASSED counts fragments that pass the depth test).

    What will happen if you draw an object and then draw another closer to the near plane that completely covers the first? What if you drew them in the opposite order?

    The answers to these questions will be determined by the depth testing state in OpenGL. Different state settings can give different answers.

    If you want a list of all the items that are under the pixel you can just disable depth testing and you'll get your list (but you won't know the depth order).

    If you want depth order you could turn on depth testing but use the depth test GL_ALWAYS and then read back the depth buffer after rendering each primitive (but this can be bad for performance, depending on exactly how you read it).

    You can get the top-most object(s) but you'll need two rendering passes. The first one you render normally with GL_LESS into the color and depth buffers. The second time you disable writes to the color and depth buffers use GL_LEQUAL and perform the SAMPLES_PASSED queries.

Similar Threads

  1. Cannot pick object using ray casting method
    By mobeen in forum OpenGL: Basic Coding
    Replies: 3
    Last Post: 03-09-2011, 04:36 PM
  2. Color Picking Method for selecting primitives..
    By rakesh_thp in forum OpenGL: Basic Coding
    Replies: 7
    Last Post: 11-14-2009, 09:01 AM
  3. Alternate method to Ray Picking
    By MrPickle in forum OpenGL: Basic Coding
    Replies: 1
    Last Post: 05-03-2008, 08:31 PM
  4. Object Picking
    By Montoya in forum OpenGL: Basic Coding
    Replies: 1
    Last Post: 02-22-2003, 12:12 AM
  5. Which picking method would you recommend?
    By Batti in forum OpenGL: Basic Coding
    Replies: 4
    Last Post: 07-03-2002, 07:18 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Proudly hosted by Digital Ocean