opengl用鼠标选择球体
我在3d空间中有很多球体,用户应该可以通过鼠标点击来选择。现在我看到了一些使用gluUnProject的例子,所以我尝试了一下。所以我有(如果我错了,请纠正我的每一步,因为我对其中的任何部分都不是100%确定): 然后,使用鼠标单击的x和y以及球体中心的位置:opengl用鼠标选择球体,opengl,pyopengl,Opengl,Pyopengl,我在3d空间中有很多球体,用户应该可以通过鼠标点击来选择。现在我看到了一些使用gluUnProject的例子,所以我尝试了一下。所以我有(如果我错了,请纠正我的每一步,因为我对其中的任何部分都不是100%确定): 然后,使用鼠标单击的x和y以及球体中心的位置: def is_picking(x, y, point): ray_start = compute_pos(x, y, -1) ray_end = compute_pos(x, y, 1) d = _compute_
def is_picking(x, y, point):
ray_start = compute_pos(x, y, -1)
ray_end = compute_pos(x, y, 1)
d = _compute_2d_distance( (ray_start[0], ray_start[1]),
(ray_end[0], ray_end[1]),
(point[0], point[1]))
if d > CUBE_SIZE:
return False
d = _compute_2d_distance( (ray_start[0], ray_start[2]),
(ray_end[0], ray_end[2]),
(point[0], point[2]))
if d > CUBE_SIZE:
return False
d = _compute_2d_distance( (ray_start[1], ray_start[2]),
(ray_end[1], ray_end[2]),
(point[1], point[2]))
if d > CUBE_SIZE:
return False
return True
因为我的3d几何不太好,我计算了两个点作为光线的起点和终点,进入2d三次,一次消除一个维度,然后计算直线和球体中心之间的距离。如果其中任何距离大于我的球体光线,则不会单击。我认为距离的公式是正确的,但只是以防万一:
def _compute_2d_distance(p1, p2, target):
'''
Compute the distance between the line defined by two points and a target point.
@param p1: first point that defines the line
@param p2: second point that defines the line
@param target: the point to which distance needs to be computed
@return: distance from point to line
'''
if p2[0] != p1[0]:
if p2[1] == p1[1]:
return abs(p2[0] - p1[0])
a = (p2[1] - p1[1])/(p2[0] - p1[0])
b = -1
c = p1[1] + p1[0] * (p2[1] - p1[1]) / (p2[0] - p1[0])
d = abs(a * target[0] + b * target[1] + c) / math.sqrt(a * a + b * b)
return d
if p2[0] == p1[0]:
d = abs(p2[1] - p1[1])
return d
return None
现在代码在开始位置似乎工作正常。但是,当你使用鼠标和屏幕旋转一点点后,任何东西都不会像预期的那样工作。嗨,有很多解决此类问题的方法 光线投射是最好的方法之一,但它涉及很多几何知识,一点也不容易 此外,gluUnProject在其他OpenGL实现中不可用,例如用于移动设备的ES(尽管您可以在矩阵操作函数中编写它) 我个人更喜欢颜色选择解决方案,它非常灵活,计算速度也非常快 其思想是在屏幕外缓冲区上使用给定的唯一颜色渲染可选择(仅可用于性能提升的可选择) 然后在用户单击的坐标处获取像素的颜色,并选择相应的3D对象 干杯
Maurizio Benedetti感谢您的投入,但我真的不知道如何/是否可以将其应用到我的解决方案中。所有可选择的球体必须具有相同的颜色。当然,您可以轻松实现这一点。为了实现这一点,您可以在标准渲染帧中使用球体自身的颜色渲染球体,在完成选择后,您可以在屏幕外使用预先指定的颜色以平面着色方式渲染对象,而不使用灯光。“Maurizio Benedetti”是正确的,颜色选择器是最好的方法。也可以使用对象的指针作为颜色值。当然,如果你制作一个64位的应用程序,你必须使用一个64位的纹理,或者在两个32位的纹理之间分割指针。我想我已经开始理解了,但我仍然不清楚“屏幕外渲染通道”意味着什么。你能解释一下吗,或者给我举个例子?非常感谢。哦,对于性能问题,所有的渲染都是使用着色器完成的。这有什么影响吗?
def _compute_2d_distance(p1, p2, target):
'''
Compute the distance between the line defined by two points and a target point.
@param p1: first point that defines the line
@param p2: second point that defines the line
@param target: the point to which distance needs to be computed
@return: distance from point to line
'''
if p2[0] != p1[0]:
if p2[1] == p1[1]:
return abs(p2[0] - p1[0])
a = (p2[1] - p1[1])/(p2[0] - p1[0])
b = -1
c = p1[1] + p1[0] * (p2[1] - p1[1]) / (p2[0] - p1[0])
d = abs(a * target[0] + b * target[1] + c) / math.sqrt(a * a + b * b)
return d
if p2[0] == p1[0]:
d = abs(p2[1] - p1[1])
return d
return None