进行 2 次旋转时对象会重置

Object get reset when doing 2 rotation

我正在尝试使用 3d 按钮旋转对象 space 当我在 x 轴上旋转对象后在 y 轴上旋转对象时 在我首先旋转它之前,位置已重置

angle = [0, 0, 0]
glPushMatrix()
if self.selected_angle == 0:
    glRotatef(angle[0], 1, 0, 0)
elif self.selected_angle == 1:
    glRotatef(angle[1], 0, 1, 0)
elif self.selected_angle == 2:
    glRotatef(angle[2], 0, 0, 1)
model.render()
glPopMatrix()
if keys[K_o]:
    selected_angle = 0
    angle[0] += 1
if keys[K_i]:
    selected_angle = 0
    angle[0] -= 1
if keys[K_k]:
    selected_angle = 1
    angle[1] += 1
if keys[K_j]:
    selected_angle = 1
    angle[1] -= 1
if keys[K_m]:
    selected_angle = 2
    angle[2] += 1
if keys[K_n]:
    selected_angle = 2
    angle[2] -= 1

简短的回答是:删除 glPushMatrix 和 glPopMatrix 调用。 PopMatrix 还原自 PushMatrix 以来所做的更改。

您只提供了一小部分代码,因此我创建了一个包含您的代码的示例。如果删除了 Push\PopMatrix 调用,则代码可以正常工作。包含 Push\Pop 调用后,立方体在旋转停止后恢复到其原始位置。

此外 - 我注意到您代码中的按键事件会增加每个循环的角度,因此在按住按键时旋转实际上会加速。我不知道这是不是故意的,但我把它留在里面了。

import pygame
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *

verticies = (
(1, -1, -1),(1, 1, -1),(-1, 1, -1),(-1, -1, -1),
(1, -1, 1),(1, 1, 1),(-1, -1, 1),(-1, 1, 1)
)

edges = (
(0,1),(0,3),(0,4),(2,1),(2,3),(2,7),
(6,3),(6,4),(6,7),(5,1),(5,4),(5,7)
)

class CCube():
    def render(self):  # draw cube
        glBegin(GL_LINES)
        for edge in edges:
            for vertex in edge:
                glVertex3fv(verticies[vertex])
        glEnd()
    def DoRotate(self, selected_angle):  # rotate cube
        self.selected_angle = selected_angle
        #glPushMatrix()  # save state
        if self.selected_angle == 0:
            glRotatef(angle[0], 1, 0, 0)
        elif self.selected_angle == 1:
            glRotatef(angle[1], 0, 1, 0)
        elif self.selected_angle == 2:
            glRotatef(angle[2], 0, 0, 1)
        self.render()  #draw cube
        #glPopMatrix()   # revert state


angle=[0,0,0] # initial angle speed

def main():
    pygame.init()
    display = (800,600)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)

    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

    glTranslatef(0.0,0.0, -5) # move cube into screen

    cc = CCube()
    
    while True:
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)  # clear screen
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        keys = pygame.key.get_pressed()
        selected_angle = -1
        if keys[K_o]:
            selected_angle = 0
            angle[0] += 1
        if keys[K_i]:
            selected_angle = 0
            angle[0] -= 1
        if keys[K_k]:
            selected_angle = 1
            angle[1] += 1
        if keys[K_j]:
            selected_angle = 1
            angle[1] -= 1
        if keys[K_m]:
            selected_angle = 2
            angle[2] += 1
        if keys[K_n]:
            selected_angle = 2
            angle[2] -= 1
        if (selected_angle > -1): CCube().DoRotate(selected_angle)  # rotate if key pressed
        
        cc.render()  # draw cube
        #glRotatef(1, 3, 1, 1)
        #Cube()
        pygame.display.flip()
        pygame.time.Clock().tick(30) # max FPS

main()

如果您想保留 push\pop,可以使用此代码。它在绘制之前设置对象角度。

import pygame
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *

verticies = (
(1, -1, -1),(1, 1, -1),(-1, 1, -1),(-1, -1, -1),
(1, -1, 1),(1, 1, 1),(-1, -1, 1),(-1, 1, 1)
)

edges = (
(0,1),(0,3),(0,4),(2,1),(2,3),(2,7),
(6,3),(6,4),(6,7),(5,1),(5,4),(5,7)
)

class CCube():
    def render(self):  # draw cube
        glBegin(GL_LINES)
        for edge in edges:
            for vertex in edge:
                glVertex3fv(verticies[vertex])
        glEnd()
        
    def DoRotate(self): # rotate cube
        glPushMatrix()  # save state
        glRotatef(angle[0], 1, 0, 0)
        glRotatef(angle[1], 0, 1, 0)
        glRotatef(angle[2], 0, 0, 1)
        self.render()   # draw cube
        glPopMatrix()   # revert state
        

angle=[0,0,0] # initial angle speed

def main():
    pygame.init()
    display = (800,600)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL)

    gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

    glTranslatef(0.0,0.0, -5) # move cube into screen

    cc = CCube()
    
    while True:
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)  # clear screen
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
        keys = pygame.key.get_pressed()
        if keys[K_o]: angle[0] += 1
        if keys[K_i]: angle[0] -= 1
        if keys[K_k]: angle[1] += 1
        if keys[K_j]: angle[1] -= 1
        if keys[K_m]: angle[2] += 1
        if keys[K_n]: angle[2] -= 1
        cc.DoRotate()  # draw cube
        pygame.display.flip()
        pygame.time.Clock().tick(30) # max FPS

main()

请注意,我使用此示例开头:https://pythonprogramming.net/opengl-rotating-cube-example-pyopengl-tutorial/