假设我像这样做一个四边形:
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();
好的,现在说我想确定用户是否在该四边形内部单击。当您单击时,您会收到屏幕坐标,因此,如果您的主窗口是600x600 像素,则您的点击将产生小于 600 的 x 和 y 值。但是我正在将点击次数(375,400(与使用创建的四边形进行比较从 -1.0 到 1.0 的值来定义 4 个顶点。
如何确定用户是否在四边形内部单击了?
我目前看到 2 种方法可以做到这一点。
-
如果您的"界面"是完全2D的并直接映射到屏幕上 - 则可以仅使用屏幕坐标进行绘制。只需设置正确的正交矩阵,您的点击坐标将与 2D 元素坐标相同 - 简单的范围比较(x
-
如果第一个变体不适合您的情况 - 您需要映射 2D 坐标以查看空间并使用结果点作为光线方向。然后追踪此光线与要单击的元素平面的交点。看看 http://www.toymaker.info/Games/html/picking.html - 没关系,它是用于 d3d,数学总是相同的(。然后,当您在您感兴趣的飞机上获取生成的点击点时 - 这又只是范围比较(尽管如果您的飞机不平行于屏幕,它会有点棘手 - 但我认为它仍然是同一个问题(。
我从来没有在这里得到一个有用的答案,但我最终在第二天就弄清楚了。我的盒子是使用从 -1 到 1 的坐标绘制的。但是我的点击有大屏幕坐标,例如 200,300。我需要知道如何将 -1 转换为 1 转换为屏幕坐标,或者如何绘制兼容的坐标。
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();
这就是我所要做的就是将我的盒子画成大约 200,300,然后我可以在每次点击时简单地检查我的盒子的边界。
最简单、最准确(但不一定是最有效的(方法:
再次渲染场景(到屏幕外缓冲区中(,目标对象为白色,其他所有对象均为黑色。 如果光标下方的像素为白色,则表示已单击目标。 如果您希望能够单击一些透明材质,只需跳过渲染这些对象即可。
为了提高效率,您可以在关闭混合并为每个对象使用唯一颜色(可能是索引(的情况下执行此操作。 使用新的 OpenGL 功能在正常渲染期间填充选取器颜色平面,而不是进行额外的传递。