python - 轨迹球转动不正确

标签 python python-3.x opengl pygame pyopengl

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

但是得到旋转轴后好像没有正确转动

这是我的代码片段

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])

最佳答案

通常您的代码工作正常。根据您编写的引用资料,您的 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),因为当鼠标在球体外部单击时,可能会发生奇怪的事情,而第一个代码将形状近似为 双曲线表(在 this reference 之后)和第二个在 this reference 之后.

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

此外,旋转向量应该归一化:

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 .这样旋转是在对象坐标中进行的。我粘贴了描述,但请遵循上面的详细信息。

An extra trick is converting the rotation axis from camera coordinates to object coordinates. It's useful when the camera and object are placed differently. For instance, if you rotate the object by 90° on the Y axis ("turn its head" to the right), then perform a vertical move with your mouse, you make a rotation on the camera X axis, but it should become a rotation on the Z axis (plane barrel roll) for the object. By converting the axis in object coordinates, the rotation will respect that the user work in camera coordinates (WYSIWYG). To transform from camera to object coordinates, we take the inverse of the MV matrix (from the MVP matrix triplet).

关于python - 轨迹球转动不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62996720/

相关文章:

python - 如何在Python中使用模板库

python - 当 Python 从命令行运行时导入 urllib.parse 失败

python - 重新排列 linregress python 中的标题

python - Pi 计算器输出问题

python - NOAA Weather REST API 在使用 curl 请求时导致错误

python-3.x - 将图像数据集拆分为训练测试数据集

python - 如何使用 matplotlib 缩放轴标签?

c++ - 移植 OpenGL 矩阵运算以 boost QVM

OpenGL - 使用 gluLookAt 绕立方体旋转速度非常快

c++ - 使用 OpenGL 的 C++ 代码中未解析的外部