简体   繁体   中英

Object get reset when doing 2 rotation

I'm trying to rotate an object with button in 3d space When i rotate the object in y-axis after rotating it in x-axis the position got reset to before i rotate it in the first place

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

The short answer is: Remove the glPushMatrix and glPopMatrix calls. PopMatrix reverts the changes you made since PushMatrix.

You only provided a small part of you code, so I created an example including your code. If the Push\PopMatrix calls are removed, the code works correctly. With the Push\Pop calls included, the cube reverts back to it's original position after rotation stops.

Also - I noticed that the key events in your code increase the angle at each loop, so the rotation actually accelerates when holding down the key. I don't know if this was intentional, but I left it in.

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

If you want to keep the push\pop, you can use this code. It sets the object angle just before drawing.

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

Note that I used this example to start with: https://pythonprogramming.net/opengl-rotating-cube-example-pyopengl-tutorial/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM