不带父子关系的多轴旋转- OpenGL着色器

n53p2ov0  于 2023-10-18  发布在  其他
关注(0)|答案(1)|浏览(90)

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

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()
qv7cva1a

qv7cva1a1#

矩阵乘法不是commutative。当矩阵相乘时,顺序很重要,这是数学事实。你的问题中的两个代码段之间有很大的区别。第一个基于旋转创建了一个全新的矩阵,

model = rX * rZ * rY

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

model = rX * rY * model

不要对Angular 求和,而是逐步更改模型变换,就像在遗留OpenGL代码中一样。这意味着,如果你正在做player_rotation_x += rotation_x,你不应该使用player_rotation_x,而是rotation_x来计算旋转矩阵。使用identity matrix初始化模型矩阵:

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

根据新的增量旋转Angular 计算旋转矩阵,并将它们与模型矩阵连接起来:

rX = np.array([[1, 0, 0, 0],
    [0, cos(rotation_x), sin(rotation_x), 0],
    [0, -sin(rotation_x), cos(rotation_x), 0],
    [0, 0, 0, 1]])
rZ = np.array([[cos(-rotation_z), -sin(-rotation_z), 0, 0],
    [sin(-rotation_z), cos(-rotation_z), 0, 0],
    [0, 0, 1, 0],
    [0, 0, 0, 1]])
rY = np.array([[cos(rotation_y), 0, -sin(rotation_y), 0],
    [0, 1, 0, 0],
    [sin(rotation_y), 0, cos(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), rotation_x, glm.vec3(1, 0, 0))
rotation = glm.rotate(rotation, rotation_z, glm.vec3(0, 0, 1)) *
rotation = glm.rotate(rotation, rotation_y, glm.vec3(0, 1, 0)) *
model = rotation * model;

相关问题