如图所示
我绘制了一组轮廓(多边形)作为GL_LINE_STRIP。 现在我想选择鼠标下的曲线(多边形)进行删除,在3D中移动..等。
我想知道使用哪种方法:
1.使用OpenGL挑选和选择。 (glRenderMode(GL_SELECT))
2.使用手动碰撞检测,使用拾取光线并检查光线是否在每个多边形内。
答案 0 :(得分:16)
我强烈建议不要使用GL_SELECT 。这种方法很老,在新的GL版本中不存在,你可能会遇到现代图形卡的问题。不要指望硬件支持它 - 可能你会在许多GPU上遇到这种模式的软件(驱动程序)后备,前提是它可以工作。使用风险自负:)
让我为您提供另一种选择。
对于坚固的大型物体,有一种古老而好的选择方法:
这为您提供了非常可靠的“每个对象”拣选方法。此外,只使用最少的每像素操作绘制和清除1个像素并不会真正损害您的性能,除非您缺少顶点处理能力(我认为不太可能)或者确实有很多对象并且可能会获得CPU-限制了绘制调用的数量(但是,我相信如果您可以按照像素数据传递颜色,则可以将其优化为单个绘制调用)。
RGB中的颜色是3个无符号字节,但是应该可以另外使用帧缓冲区的alpha通道作为最后一个字节,所以你总共得到4个字节 - 足以存储任何32位指针对象作为颜色。
或者,您可以创建一个具有特定像素格式的专用帧缓冲对象(如GL_R32UI
,如果需要64位,则甚至GL_RG32UI
)。
对于严格的几何方法,以上是一个很好的快速替代方案(在可靠性和实现时间方面)。
答案 1 :(得分:5)
我发现在新的GPU上,GL_SELECT模式非常慢。我用几种不同的方法来解决这个问题。
第一个是进行CPU碰撞测试,但是效果并不像我想的那么快。当你将光线投射到屏幕上时(使用gluUnproject)然后试图找到鼠标正在碰撞的对象,它肯定会减慢速度。我获得满意速度的唯一方法是使用八叉树来减少碰撞测试次数,然后进行边界框碰撞测试 - 但是,这导致了一种不是像素完美的方法。
我选择的方法是首先找到鼠标下的所有对象(使用gluUnproject和边界框碰撞测试),这通常非常快。然后,我将可能与后备缓冲器中的鼠标碰撞的每个对象渲染为不同的颜色。然后我使用glReadPixel获取鼠标下的颜色,并将其映射回对象。 glReadPixel是一个慢速调用,因为它必须从帧缓冲区读取。但是,每帧执行一次,最终花费的时间可以忽略不计。如果您愿意,可以通过渲染到PBO来加快速度。
Giawa
答案 2 :(得分:3)
umanga,不知道如何回复内联...也许我应该注册:)
首先,我必须为给你错误的算法道歉 - 我做了背面剔除一个。但是你需要的那个非常相似,这就是为什么我感到困惑...'哦。
如前所述,将相机位置设置为鼠标矢量。
对于每个轮廓,循环遍历其中的所有坐标(0-1,1-2,2-3,... n-0),并像以前一样从它们中取出一个vec。即走完轮廓。
现在做两者的交叉刺激(轮廓边缘到鼠标vec),而不是像我之前说过的那样,对所有对进行,并将向量加起来。
最后找到结果向量的大小。如果结果为零(考虑到舍入误差),那么你的形状外 - 无论面对。如果你有兴趣面对然后而不是mag你可以用鼠标矢量做点刺,找到面对并测试符号+/-。
它的工作原理是因为算法依次找到从矢量线到每个点的距离。当你总结它们并且你在外面时它们都会被取消,因为轮廓是闭合的。如果你的内心然后他们都总结。它实际上是高斯物理中的电磁场定律......
参见:http://en.wikipedia.org/wiki/Gauss%27s_law并注意“等式的右边是S所包围的总电荷除以电常数”,注明“封闭”一词 - 即零意味着没有封闭。
您仍然可以使用速度的边界框进行优化。
答案 3 :(得分:1)
在过去,我使用GL_SELECT来确定哪些对象贡献了感兴趣的像素,然后使用计算几何来获得与对象的准确交集(如果需要)。
答案 4 :(得分:1)
您希望通过单击轮廓(在边缘上)还是在多边形内部进行选择?您的第二种方法听起来像是要在内部点击以选择最紧密的包含多边形。我不认为渲染GL_SELECT
后GL_LINE_STRIP
会使内部对点击做出响应。
如果这是一个真正的轮廓图(从图像中我认为不是,边缘看起来相交)那么可以使用更简单的算法。
答案 5 :(得分:1)
你不能使用选择,如果你留在线上,因为你必须点击所呈现的线条像素,而不是界定它们的线条内的空间,我读到你想做的事情。
你可以使用Kos的答案,但是为了渲染你需要的空间来填充它,这将涉及将所有轮廓转换为凸起的类型,这是很痛苦的。所以我认为这有时会起作用,在某些情况下给出错误的答案,除非你这样做。
您需要做的是使用CPU。您具有视口和透视矩阵的视图范围。使用鼠标坐标,生成鼠标指针向量的视图。你也有轮廓的所有坐标。
取第一个轮廓的第一个坐标并将矢量制作到第二个坐标。制作一个矢量。取第3个坐标并从2到3制作一个向量,并在你的轮廓周围重复,最后再将最后一个从坐标转回到0。对于每对按顺序找到叉积并总结所有结果。当你有最终的求和向量时,保持它并用鼠标指针方向向量做一个点积。如果它是+ ve然后鼠标在轮廓内,如果它的-ve然后它不是,如果为0那么我猜测轮廓的平面和鼠标的方向是平行的。
对每个轮廓执行此操作,然后您将知道它们中的哪些被鼠标尖刺。它取决于你想要从那一组中选择哪一个。最高的Z?
这听起来像很多工作,但它不是太糟糕,并会给出正确的答案。您可能希望另外保留所有轮廓的边界框,然后您可以通过对完整向量进行相同的数学运算来提前排除鼠标向量的边界框,但仅限于4边,如果不在内部则轮廓不能任
答案 6 :(得分:0)
第一种易于实施和广泛使用。