Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
opengl用鼠标选择球体_Opengl_Pyopengl - Fatal编程技术网

opengl用鼠标选择球体

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_

我在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_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