Pergunta

Say I make a quad like so:

float botBaseY = -0.5;
glBegin(GL_QUADS); // Box
    glVertex2f(-.05, botBaseY + -.05);
    glVertex2f(-.05, botBaseY + .05);
    glVertex2f(.05, botBaseY + .05);
    glVertex2f(.05, botBaseY + -.05);
glEnd();

OK, well now say I want to determine if the user clicked inside of that quad. Well when you click, you receive screen coordinates, so if your main window is 600x600 pixels, then your click will yield an x and y value less than 600. But I'm comparing a click at say (375,400) to a quad that was created using values from -1.0 to 1.0 to define the 4 vertices.

How can I determine if the user clicked inside of the quad?

Foi útil?

Solução 2

I never ended up getting a useful answer on here, but I did end up figuring it out the next day. My box was being drawn using coordinates that were from -1 to 1. But my click had large screen coordinates such as 200,300. I needed to know how to convert the -1 to 1 into screen coordinates, or how to just draw it compatible coordinates.

glMatrixMode(GL_PROJECTION);
gluOrtho2D(0, 400, 0, 400);
glBegin(GL_QUADS); // Box
    glVertex2f(xOffset + topBaseX + -15, topBaseY + -15);// bottom left vert
    glVertex2f(xOffset + topBaseX + -15, topBaseY + 15); // top left vert
    glVertex2f(xOffset + topBaseX + 15, topBaseY + 15);// top right vert
    glVertex2f(xOffset + topBaseX + 15, topBaseY + -15);// bottom right vert
glEnd();
glLoadIdentity();

That was all I had to do to draw my box at something like 200,300 and then I could simply check the boundaries of my box on each click.

Outras dicas

I currently see 2 ways to do this.

  1. if your 'interface' is completely 2D and directly mapped into screen - you could just use screen coordinates for drawing. Just set correct orthographic matrix and your click coordinates will be the same as 2D elements coordinates - simple range comparison (x < click_x < x+width). See gluOrtho2D, glOrtho manuals (please note that glOrtho and other matrix functions are not available in newest GL profiles).

  2. if first variant isn't fitting your situation - you need to map 2D coordinates to view space and use resulting point as ray direction. Then trace this ray's intersection with element's plane you want to click. Take a look at http://www.toymaker.info/Games/html/picking.html - doesn't matter that it's for d3d, math is always the same). Then, when you'll take resulting click point on a plane you've interested in - it's again just range comparison (although it will be a little trickier if your plane is not parallel to screen - but i don't think it still the same question).

Easiest and most accurate (but not necessarily most efficient) way:

Render the scene again (into an off-screen buffer) with the target object white and all else black. If the pixel under the cursor is white, the target was clicked. If you want to be able to click through some transparent materials, just skip rendering those objects.

For efficiency, you can do this with blending turned off and a unique color (perhaps an index) for each object. And use new OpenGL capabilities to fill the picker color plane during normal rendering instead of taking an additional pass.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top