Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm attempting to check which object the user is hovering over. While everything seems to be just how I'd think it should be, I'm not able to get the correct color due to the second time I draw (without picking colors). Here is my rendering code:

public void render() {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    camera.applyTranslations();

    scene.pick();

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    camera.applyTranslations();

    scene.render();
}

And here is what gets called on each block/tile on "scene.pick()":

public void pick() {
    glColor3ub((byte) pickingColor.x, (byte) pickingColor.y, (byte) pickingColor.z);
    draw();

    glReadBuffer(GL_FRONT);
    ByteBuffer buffer = BufferUtils.createByteBuffer(4);
    glReadPixels(Mouse.getX(), Mouse.getY(), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

    int r = buffer.get(0) & 0xFF;
    int g = buffer.get(1) & 0xFF;
    int b = buffer.get(2) & 0xFF;

    if(r == pickingColor.x && g == pickingColor.y && b == pickingColor.z) {
        hovered = true;
    } else {
        hovered = false;
    }
}

I believe the problem is that in the method of each tile/block called by scene.pick(), it is reading the color from the regular drawing state, after that method is called somehow. I believe this because when I remove the "glReadBuffer(GL_FRONT)" line from the pick method, it seems to almost fix it, but then it will also select blocks behind the one you are hovering as it is not only looking at the front.

If you have any ideas of what to do, please be sure to reply!/

EDIT: Adding scene.render(), tile.render(), and tile.draw()

scene.render:

public void render() {
    for(int x = 0; x < tiles.length; x++) {
        for(int z = 0; z < tiles.length; z++) {
            tiles[x][z].render();
        }
    }
}

tile.render:

public void render() {
    glColor3f(color.x, color.y, color.z);
    draw();
    if(hovered) {
        glColor3f(1, 1, 1);
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
        draw();
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }
}

tile.draw:

public void draw() {
    float x = position.x, y = position.y, z = position.z;

    //Top
    glBegin(GL_QUADS);
    glVertex3f(x, y + size, z);
    glVertex3f(x + size, y + size, z);
    glVertex3f(x + size, y + size, z + size);
    glVertex3f(x, y + size, z + size);
    glEnd();

    //Left
    glBegin(GL_QUADS);
    glVertex3f(x, y, z);
    glVertex3f(x + size, y, z);
    glVertex3f(x + size, y + size, z);
    glVertex3f(x, y + size, z);
    glEnd();

    //Right
    glBegin(GL_QUADS);
    glVertex3f(x + size, y, z);
    glVertex3f(x + size, y + size, z);
    glVertex3f(x + size, y + size, z + size);
    glVertex3f(x + size, y, z + size);
    glEnd();

}

(The game is like an isometric game. That's why I only draw 3 faces.)

share|improve this question
    
whats getting called in scene.render()? –  XiaoChuan Yu Oct 23 '12 at 23:53
    
Here, I'll add those too. –  Tom Johnson Oct 23 '12 at 23:57
    
So, hovered is a property of scene, which gets set in scene.pick(), but it gets referenced in each tile.render() call? That seems not right. –  Seth Battin Oct 24 '12 at 1:40
1  
@TomJohnson The reason I bring it up is that it is used in your tile render, but if it is improperly assigned, perhaps that is part of your problem. You have a variable that is mysteriously not reading like it is supposed to. Perhaps it's the variable that is weirdly used like a global value. –  Seth Battin Oct 26 '12 at 1:51
1  
The boolean "hovered" is in the tile class, if that is what you had just edited your question to mean. –  Tom Johnson Oct 27 '12 at 23:40
show 1 more comment

1 Answer

It is hard to say exactly what is broken, but I can make a few suggestions.

  1. Generally, the front buffer is what is currently shown, and drawing calls that are being processed are drawn to the back buffer. Once the entire scene is rendered, the back buffer is copied to the front buffer. Therefore I think that you should read from the back buffer, because the front buffer will always contain the final scene, where you have drawn over the colors you want to pick from. (i.e. change your call for glReadBuffer(GL_FRONT) to glReadBuffer(GL_BACK)).

  2. Antialiasing (multisampling and supersampling) and transparency must be disabled for color picking to work. The colors you are picking from encode object IDs, and it does not make sense to blend IDs.

  3. Make sure that the drawing calls are flushed before reading. This may be implied by the pixel reading commands, and may not. It may be good to add an explicit flush command to make sure for debugging at least.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.