Hello Guest

[SOLVED] IntBuffer not enough for Picking?

  • 2 Replies
  • 3417 Views
*

Offline manji

  • *
  • 41
    • toyWars
[SOLVED] IntBuffer not enough for Picking?
« on: November 10, 2010, 13:33:18 »
I am using picking to find out if there is an object in front of my main character. So, I select a region on the screen(where my character is), and I find the depths of all the objects I want it this region. If the smallest depth does not belong to my character, then this means that another object is closer to me (the screen), and I act accordingly.

This technique works great, apart from the case when the camera is really close to my character. I do not mean inside it, where maybe I could understand if it got confused, I mean very close to it. In this case, it does not detect the depth of my character, and goes to the next one. After I printed out the current depth of my character for each frame I was getting close to it, I found out that it stopped when reaching somewhere close to -2147471104. Which is very close to the minimum int value, -2147483648. So I though that this must be why.

The code I use is to start picking:
Code: [Select]
private void startPicking3D(int xHead, int yHead, int xSide, int ySide){
    // The selection buffer
    selBuffer = ByteBuffer.allocateDirect(1024).order(ByteOrder.nativeOrder()).asIntBuffer();
    IntBuffer vpBuffer = ByteBuffer.allocateDirect(64).order(ByteOrder.nativeOrder()).asIntBuffer();
    // The size of the viewport. [0] Is <x>, [1] Is <y>, [2] Is <width>, [3] Is <height>
    int[] viewport = new int[4];

    // The number of "hits" (objects within the pick area).

    // Get the viewport info
    GL11.glGetInteger(GL11.GL_VIEWPORT, vpBuffer);
    vpBuffer.get(viewport);

    // Set the buffer that OpenGL uses for selection to our buffer
    GL11.glSelectBuffer(selBuffer);

    // Change to selection mode
    GL11.glRenderMode(GL11.GL_SELECT);

    // Initialize the name stack (used for identifying which object was selected)
    GL11.glInitNames();        

    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glPushMatrix();
    GL11.glLoadIdentity();

    // create 5x5 pixel picking region near cursor location */
    GLU.gluPickMatrix( (float) xHead, (float) yHead, xSide, ySide, IntBuffer.wrap(viewport));

    GLU.gluPerspective(65.0f,
                      (float)1280/(float)800,
                      0.1f,
                      150.0f);

    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glLoadIdentity();
}

The code to stop picking:
Code: [Select]
public void stopPicking(){
    GL11.glMatrixMode(GL11.GL_PROJECTION);
            GL11.glPopMatrix();
    GL11.glMatrixMode(GL11.GL_MODELVIEW);

    hits = 0;
    hits = GL11.glRenderMode(GL11.GL_RENDER);
}

And the the code for finding out selected object:
Code: [Select]
public int getSelectedEntity(){
    int[] buffer = new int[256];
    int EntityID = -1;

    selBuffer.get(buffer);
    // Objects Were Drawn Where The Mouse Was
    if (hits > 0) {
        // If There Were More Than 0 Hits
        EntityID = buffer[3]; // Make Our Selection The First Object

        int depth = buffer[1]; // Store How Far Away It Is

        for (int i = 1; i < hits; i++) {
            // Loop Through All The Detected Hits
            // If This Object Is Closer To Us Than The One We Have Selected
            if (buffer[i * 4 + 1] < (int) depth) {
                EntityID = buffer[i * 4 + 3]; // Select The Closest Object
                depth = buffer[i * 4 + 1]; // Store How Far Away It Is
            }
        }
    }
    return EntityID;
}

My questions are:
Are these big depth values generally normal?
If yes, then should I use long? But how, considering that selBuffer is declared as IntBuffer and glSelectBuffer requires IntBuffer only.
« Last Edit: November 16, 2010, 12:18:09 by manji »

Re: IntBuffer not enough for Picking?
« Reply #1 on: November 10, 2010, 14:07:25 »
You should not use GL_SELECT - it is slow and very limited. A much better approach is to complete the intersections yourself using bounding volumes (spheres, boxes etc). If you use a bounding tree you can speed up these tests a lot. See here for details on how to compute such intersections.

And you should not ask GL for data you passed it (like the current matrix) - better to do the matrix math yourself (there are a lot of libs) and upload only the finished matrices to GL. This allows you to cache matrices which did not change etc.

*

Offline manji

  • *
  • 41
    • toyWars
Re: IntBuffer not enough for Picking?
« Reply #2 on: November 10, 2010, 16:15:12 »
@abdulwaheed  If you are referring to me, thnx, most of the code though was found somewhere in this forum.

@Matthias Thanks for your advice! I have now changed the way I check for a blocking objects. I had already implemented a ray-box intersection algorithm for shooting, I changed it a little and it works fine now, plus I believed I gained some fps.
Could you please elaborate more on the second part of your comment? Are you referring maybe to matrix transformations? If yes, do you happen to have any tutorials for this? Because I always read that you should always use your own custom math stuff instead of using OpenGL's methods, but I cannot find any tutorials for doing so.