【问题标题】:Trackball doesn't turn correctly轨迹球无法正确转动
【发布时间】:2020-07-20 13:42:45
【问题描述】:

我正在尝试通过引用此来源 https://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Arcballhttps://www.khronos.org/opengl/wiki/Object_Mouse_Trackball 来实现轨迹球

但在获得旋转轴后,它似乎没有正确转动

这是我的代码的一些 sn-p

def compute_z(x, y):
    # compute z from sphere model
    # sphere size = 1
    z = math.sqrt(abs(1 - math.pow(x,2) - math.pow(y,2)))
    return z

def get_rotation_axis(vect_1, vect_2):
    # determine rotation direction
    axis = np.cross(vect_1, vect_2)
    return axis

这里是主要的

    while True:
        mouse_pos = pygame.mouse.get_pos()
        
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            if event.type == pygame.MOUSEMOTION:
                if arcball_on:
                    cur_mx = mouse_pos[0]
                    cur_my = mouse_pos[1]
                    last_conv = convert_range(last_mx, last_my)
                    cur_conv = convert_range(cur_mx, cur_my)
                    a = (last_conv[0], last_conv[1], compute_z(last_conv[0], last_conv[1]))
                    b = (cur_conv[0], cur_conv[1], compute_z(cur_conv[0], cur_conv[1]))
                    angle = compute_angle(a, b)
                    axis = get_rotation_axis(a, b)
                    print(axis)
                    glRotatef(angle, axis[0], axis[1], -axis[2])

【问题讨论】:

    标签: python python-3.x opengl pygame pyopengl


    【解决方案1】:

    通常您的代码可以正常工作。根据您编写的参考资料,您的 compute_z 函数可能如下所示:

    def compute_z(x, y):
        # compute z from sphere model
        op_squared = x ** 2 + y ** 2
        r_squared = SPHERE_R ** 2
        if op_squared > r_squared / 2:
            z = r_squared / 2 / math.sqrt (op_squared)
        else:
            z = math.sqrt(r_squared - op_squared)
        return z
    

    甚至更简单:

    def compute_z(x, y):
        # compute z from sphere model
        op_squared = x ** 2 + y ** 2
        r_squared = SPHERE_R ** 2
        if op_squared > r_squared:
            return 0
        else:
            return math.sqrt(r_squared - op_squared)
    

    其中SPHERE_R 是假设球体的半径(默认为1),因为当鼠标在球体外部点击时,可能会发生奇怪的事情,而第一个代码将形状近似为双曲表 em>(在this reference 之后)和第二个在this reference 之后。

    angleaxis 值在我检查时计算正确。

    另外旋转向量应该是normalized:

    def normalize(x):
        x = np.asarray(x)
        if np.linalg.norm(x):
            return x / np.linalg.norm(x)
        else:
            return x
    
    # .....
    
    a = (last_conv[0], last_conv[1], compute_z(last_conv[0], last_conv[1]))
    b = (cur_conv[0], cur_conv[1], compute_z(cur_conv[0], cur_conv[1]))
    a = normalize(a)
    b = normalize(b)
    axis = get_rotation_axis(a, b)
    axis = normalize(axis)
    

    glRotatef 函数工作正常(您也可以更改 x 轴的方向,但它仍然工作良好。

    当您执行大量旋转时,您会发现轴不是按常识放置的,因为这些旋转,但是当您使用鼠标小心缓慢地上下左右移动时 - 您会看到该轴已旋转,但立方体仍在旋转。

    有一个技巧可能会改变你正在旋转的东西,它被使用了here。这样旋转是在对象坐标中进行的。我粘贴了描述,但请遵循上面的详细信息。

    一个额外的技巧是将旋转轴从相机坐标转换为物体坐标。当相机和对象放置不同时,它很有用。例如,如果您在 Y 轴上将对象旋转 90°(“向右转头”),然后用鼠标执行垂直移动,您会在相机 X 轴上进行旋转,但它应该变成对象在 Z 轴上的旋转(平面桶滚动)。通过在对象坐标中转换轴,旋转将尊重用户在相机坐标中的工作 (WYSIWYG)。为了从相机坐标转换到物体坐标,我们采用 MV 矩阵的逆矩阵(来自 MVP 矩阵三元组)。

    【讨论】:

    • 太棒了,我没有意识到它以绝对位置方式转动。这就是为什么它似乎转向不正确
    猜你喜欢
    • 2011-12-28
    • 2012-10-02
    • 2016-03-02
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    • 2010-10-29
    相关资源
    最近更新 更多