在没有父子关系的情况下围绕多个轴旋转 - OpenGL 着色器

问题描述 投票:0回答:1

我正在尝试使用带有着色器的 PyOpenGL 围绕多个轴旋转对象。因为没有像旧 OpenGL 中那样的 glRotatef(),所以我使用 4x4 旋转矩阵。然而,由于矩阵乘法不可交换,因此它建立了这种父子关系,其中一个轴独立旋转(父轴),另一个轴基于第一个轴(子轴)旋转。我对矩阵不是很熟悉,我刚刚开始 AP 预计算,还没有接触到矩阵,但据我所知,如果不建立这种关系,就无法将旋转矩阵相乘。

这是程序示例。

model1 = np.array([[1, 0, 0, 0],
                        [0, cos(player_rotation_x), sin(player_rotation_x), 0],
                        [0, -sin(player_rotation_x), cos(player_rotation_x), 0],
                        [0, 0, 0, 1]
             ]) @ np.array([[cos(-player_rotation_z), -sin(-player_rotation_z), 0, 0],
                            [sin(-player_rotation_z), cos(-player_rotation_z), 0, 0],
                            [0, 0, 1, 0],
                            [0, 0, 0, 1]
             ]) @ np.array([[cos(player_rotation_y), 0, -sin(player_rotation_y), 0],
                            [0, 1, 0, 0],
                            [sin(player_rotation_y), 0, cos(player_rotation_y), 0],
                            [0, 0, 0, 1]])

这建立了从 x 到 y 的层次结构。

这是我尝试使用着色器而不是固定功能管道重新创建的程序示例。

rotation_matrix = (GLfloat * 16)(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)

while True:
    glPushMatrix()
    glLoadIdentity()
    glRotatef(-player_rotation_x, 1, 0, 0)
    glRotatef(-player_rotation_y, 0, 1, 0)
    glMultMatrixf(rotation_matrix)
    glGetFloatv(GL_MODELVIEW_MATRIX, rotation_matrix)
    glPopMatrix()
python opengl 3d parent-child pyopengl
1个回答
0
投票

矩阵乘法不是可交换的。当矩阵相乘时,顺序很重要,这是一个数学事实。您问题中的两个代码片段之间存在很大差异。虽然第一个基于旋转创建了一个全新的矩阵,

model = rX * rZ * rY

第二个(旧版 OpenGL)通过将当前模型矩阵与新旋转连接来更新当前模型矩阵

model = rX * rY * model

不要对角度求和,而是逐步更改模型转换,就像旧版 OpenGL 代码中的情况一样。使用单位矩阵初始化模型矩阵:

model = np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]])

根据新的增量旋转角度计算旋转矩阵并将其与模型矩阵连接:

rX = np.array([[1, 0, 0, 0],
    [0, cos(player_rotation_x), sin(player_rotation_x), 0],
    [0, -sin(player_rotation_x), cos(player_rotation_x), 0],
    [0, 0, 0, 1]])
rZ = np.array([[cos(-player_rotation_z), -sin(-player_rotation_z), 0, 0],
    [sin(-player_rotation_z), cos(-player_rotation_z), 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1]])
rY = np.array([[cos(player_rotation_y), 0, -sin(player_rotation_y), 0],
    [0, 1, 0, 0],
    [sin(player_rotation_y), 0, cos(player_rotation_y), 0],
    [0, 0, 0, 1]])
model = rX @ rZ @ rY @ model

您可以使用 PyGLMPyrr 简化该代码。这是使用 PyGlm 实现的示例。

导入PyGlm

import glm

初始化矩阵

model = glm.mat4(1)

创建旋转矩阵并与模型矩阵相乘:

rotation = glm.rotate(glm.mat4(1), player_rotation_x, glm.vec3(1, 0, 0))
glm.rotate(rotation, player_rotation_z, glm.vec3(0, 0, 1)) *
glm.rotate(rotation, player_rotation_y, glm.vec3(0, 1, 0)) *
model = rotation * model;
© www.soinside.com 2019 - 2024. All rights reserved.