四个旋转顶点之间的命中测试
Posted
技术标签:
【中文标题】四个旋转顶点之间的命中测试【英文标题】:Hit testing between four rotating vertices 【发布时间】:2013-01-20 12:56:09 【问题描述】:我的程序中有一个简单的矩形,我必须在上面进行命中测试。我正在使用 openFrameworks,但我认为这里的问题也与 OpenGL 主题有关。
public class Shape : public class ofNode
Shape()
container.setFromCenter(getPosition(), 200,100);
setPosition(ofVec3f(365, 50, 0)); //set the position of the node
lookAt(ofVec3f(0,0,0));
virtual void draw()
ofRect(container); //the 200/100 rectangle will be drawn as per the container position and dimensions
ofVec3f getTopLeft() const
return getTopLeft() * ofNode::getGlobalTransformMatrix();
ofVec3f getTopRight() const //similar - getTopRight from container and multiply
ofVec3f getBottomLeft() const //similar
ofVec3f getBottomRight() const //similar
bool hitTest(int tx, int ty)
// return true if mouse pointer is inside four vertices - hit test logic working fine
private:
ofRectagle container;
;
我遇到的问题是我在程序中旋转和平移形状:
void draw()
ofPushMatrix();
ofTranslate(600,300,0);
ofRotateY(rotate);
shape->draw();
ofCircle(shape->getTopLeft(), 10); //circle is drawn at the rectangle top left vertex on the screen but the coordinates while rotating and drawing do not change (as seen on cout)
ofCircle(shape->getTopRight(), 10); //similar
ofCircle(shape->getBottomLeft(), 10); //similar
ofCircle(shape->getBottomRight(), 10); //similar
ofPopmatrix();
在上述draw
函数中改变旋转时,点不会改变。因此,我没有合适的四个顶点来进行命中测试来确定鼠标是否在里面。
如何获取屏幕中点的位置,可以对照鼠标位置进行点击测试?
【问题讨论】:
【参考方案1】:如果你想测试鼠标指针是否在矩形的范围内,我建议你先将它们转换到屏幕空间并在那里进行测试,按照我在https://***.com/a/14424267/524368给你的总体思路
我还要说,是时候停止使用 OpenGL 的内置矩阵操作函数了。 使用它们绝对没有任何好处!有些人认为它们会被 GPU 加速,但事实并非如此。一旦您在程序中的其他点需要这些矩阵,为此滥用 OpenGL 是不切实际的。 OpenGL 毕竟不是一个数学库。在后来的版本中,整个矩阵堆栈已从 OpenGL 中删除——很好摆脱。
OpenFrameworks comes with a fully featured matrix math library。我强烈建议您使用 that。您可以使用glLoadMatrix
(固定函数管道)或glUniformMatrix
(着色器管道)将生成的矩阵提供给OpenGL。
您可以使用它来实现我在其他答案中概述的投影功能。
要测试一个点是否位于边定义的边界内,您可以使用一个称为“半边”的概念。假设你的边缘形成一个star domain 循环。然后,对于循环中的每条边,您都取该点与边的叉积。如果该点在循环定义的形状内,则所有叉积将指向同一方向。共面四边形(即投影到屏幕空间中的四边形)总是形成一个星域。
【讨论】:
如果一个点位于由一组顶点形成的多边形内,我可以在单独的应用程序中进行测试。但是,我在这里遇到的问题是“获取那些我应该测试的顶点”。我旋转的矩形/形状具有恒定的顶点。为了将顶点转换为屏幕空间,我执行了以下函数:pastebin.com/8Z2PVPq9 我期待ofWorldToScreen(getTopLeft())
能够工作并给出这些屏幕坐标,从而使这四个圆位于矩形的顶点上。但是,我得到的是:i.imgur.com/MMH2uLI.png
啊!我意识到我在唱一些愚蠢的事情。我能够获得屏幕点转换并且命中测试运行良好。我将此标记为答案,但很高兴知道如果命中测试运行良好,为什么这四个矩形没有绘制在矩形的四个顶点上(而是在屏幕上的其他地方移位)?
@user1240679:您的 ofWorldToScreen 函数有一个主要问题:它取决于全局状态。它必须在顶点也被绘制到屏幕以复制 OpenGL 的行为的那一刻调用。您能否说明您在哪里以及如何调用 ofWorldToScreen?
@user1240679:此外,当您绘制这些变换点时,您当然必须确保这些点将直接映射到视口坐标。那就是 glViewport(0,0,w,h); glOrtho(0,w,0,h, _, _);
这是我在里面使用的形状类ofWorldToScreen
pastebin.com/mnKnr0h3以上是关于四个旋转顶点之间的命中测试的主要内容,如果未能解决你的问题,请参考以下文章