如何在pyopengl中使用鼠标旋转立方体 [英] How to rotate a cube using mouse in pyopengl

查看:85
本文介绍了如何在pyopengl中使用鼠标旋转立方体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道问题出在哪里,但我想不出解决方案.问题是旋转是在固定在立方体上的轴上应用的,所以如果你旋转一个轴 Pi 弧度,那么另一个轴看起来就像鼠标控件被反转.我想让它点击鼠标左键,然后向右移动鼠标向右旋转立方体,向左移动立方体向左旋转,等等.请帮忙.

导入pygame从 pygame.locals 导入 *从 OpenGL.GL 导入 *从 OpenGL.GLU 导入 *顶点 = ((-1, -1, -1), (-1, 1, -1), (-1, 1, 1), (-1, -1, 1), (1, -1, -1), (1, 1, -1), (1, 1, 1), (1, -1, 1))边 = ((0, 1), (0, 3), (0, 4), (1, 2), (1, 5), (2, 3), (2, 6), (3, 7), (4, 5), (4, 7), (5, 6), (6, 7))人脸 = ((0, 1, 2 , 3),(4, 5, 6, 7),(0, 4, 7, 3),(1, 5, 6, 2),(2, 6, 7,3),(1, 5, 4, 0))# ==============================================================================# 顶点 = ((1, -1, -1), (1, 1, -1), (-1, 1, -1), (-1, -1, -1), (1, -1,1), (1, 1, 1), (-1, -1, 1), (-1, 1, 1))# 边 = ((0, 1), (0, 3), (0, 4), (2, 1), (2, 3), (2, 7), (6, 3), (6, 4)), (6, 7), (5, 1), (5, 4), (5, 7))# ==============================================================================定义立方体():glBegin(GL_QUADS)面对面:对于面顶点:glColor3fv((1, 0, 1))glVertex3fv(顶点[顶点])glEnd()glBegin(GL_LINES)glColor3fv((1, 1, 1))对于边缘中的边缘:对于边缘中的顶点:glVertex3fv(顶点[顶点])glEnd()定义主():pygame.init()屏幕 = (1600, 1200)display = pygame.display.set_mode(screen, DOUBLEBUF|OPENGL)gluPerspective(45, (screen[0]/screen[1]), 0.1, 500)glTranslatef(0, 0, -5)button_down = 假为真:对于 pygame.event.get() 中的事件:如果 event.type == pygame.QUIT:pygame.quit()如果 event.type == pygame.KEYDOWN:如果 event.key == pygame.K_LEFT:glTranslatef(-1, 0, 0)如果 event.key == pygame.K_RIGHT:glTranslatef(1, 0, 0)如果 event.key == pygame.K_UP:glTranslatef(0, 1, 0)如果 event.key == pygame.K_DOWN:glTranslatef(0, -1, 0)如果 event.type == pygame.MOUSEMOTION:如果 button_down == 真:glRotatef(event.rel[1], 1, 0, 0)glRotatef(event.rel[0], 0, 1, 0)打印(事件.rel)对于 pygame.mouse.get_pressed() 中的事件:打印(pygame.mouse.get_pressed())如果 pygame.mouse.get_pressed()[0] == 1:button_down = 真elif pygame.mouse.get_pressed()[0] == 0:button_down = 假glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)立方体()pygame.display.flip()pygame.time.wait(10)主要的()

解决方案

导入pygame从 pygame.locals 导入 *从 OpenGL.GL 导入 *从 OpenGL.GLU 导入 *顶点 = ((-1, -1, -1), (-1, 1, -1), (-1, 1, 1), (-1, -1, 1), (1, -1, -1), (1, 1, -1), (1, 1, 1), (1, -1, 1))边 = ((0, 1), (0, 3), (0, 4), (1, 2), (1, 5), (2, 3), (2, 6), (3, 7), (4, 5), (4, 7), (5, 6), (6, 7))人脸 = ((0, 1, 2 , 3),(4, 5, 6, 7),(0, 4, 7, 3),(1, 5, 6, 2),(2, 6, 7,3),(1, 5, 4, 0))# ==============================================================================# 顶点 = ((1, -1, -1), (1, 1, -1), (-1, 1, -1), (-1, -1, -1), (1, -1,1), (1, 1, 1), (-1, -1, 1), (-1, 1, 1))# 边 = ((0, 1), (0, 3), (0, 4), (2, 1), (2, 3), (2, 7), (6, 3), (6, 4)), (6, 7), (5, 1), (5, 4), (5, 7))# ==============================================================================定义立方体():glBegin(GL_QUADS)面对面:对于面顶点:glColor3fv((1, 0, 1))glVertex3fv(顶点[顶点])glEnd()glBegin(GL_LINES)glColor3fv((1, 1, 1))对于边缘中的边缘:对于边缘中的顶点:glVertex3fv(顶点[顶点])glEnd()定义主():pygame.init()屏幕 = (1600, 1200)display = pygame.display.set_mode(screen, DOUBLEBUF|OPENGL)glMatrixMode(GL_PROJECTION)gluPerspective(45, (screen[0]/screen[1]), 0.1, 500)button_down = 假glMatrixMode(GL_MODELVIEW)modelMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)为真:glPushMatrix()glLoadIdentity()对于 pygame.event.get() 中的事件:如果 event.type == pygame.QUIT:pygame.quit()如果 event.type == pygame.KEYDOWN:如果 event.key == pygame.K_LEFT:glTranslatef(-1, 0, 0)如果 event.key == pygame.K_RIGHT:glTranslatef(1, 0, 0)如果 event.key == pygame.K_UP:glTranslatef(0, 1, 0)如果 event.key == pygame.K_DOWN:glTranslatef(0, -1, 0)如果 event.type == pygame.MOUSEMOTION:如果 button_down == 真:glRotatef(event.rel[1], 1, 0, 0)glRotatef(event.rel[0], 0, 1, 0)打印(事件.rel)对于 pygame.mouse.get_pressed() 中的事件:打印(pygame.mouse.get_pressed())如果 pygame.mouse.get_pressed()[0] == 1:button_down = 真elif pygame.mouse.get_pressed()[0] == 0:button_down = 假glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)glMultMatrixf(modelMatrix)modelMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)glLoadIdentity()glTranslatef(0, 0, -5)glMultMatrixf(modelMatrix)立方体()glPopMatrix()pygame.display.flip()pygame.time.wait(10)主要的()

I know what the problem is but i cannot figure out a solution. The problem is that the rotation is applied with the axis fixed on the cube so that if you turn one axis Pi radians then the other axis will look like the mouse controls are inverted. I want it to make it so clicking left mouse button and then moving the mouse to the right rotates the cube to the right, moving it to the left rotates the cube to the left, etc. Please help.

import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *

vertices = ((-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), (1, 2), (1, 5), (2, 3), (2, 6), (3, 7), (4, 5), (4, 7), (5, 6), (6, 7))
faces = ((0, 1, 2 , 3),(4,  5, 6, 7),(0, 4, 7, 3),(1, 5, 6, 2),(2, 6, 7, 3),(1, 5, 4, 0))

# =============================================================================
# vertices = ((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))
# =============================================================================

def Cube():
    glBegin(GL_QUADS)
    for face in faces:
        for vertex in face:
            glColor3fv((1, 0, 1))
            glVertex3fv(vertices[vertex])
    glEnd()

    glBegin(GL_LINES)
    glColor3fv((1, 1, 1))
    for edge in edges:
        for vertex in edge:
            glVertex3fv(vertices[vertex])
    glEnd()

def Main():
    pygame.init()
    screen = (1600, 1200)
    display = pygame.display.set_mode(screen, DOUBLEBUF|OPENGL)
    gluPerspective(45, (screen[0] / screen[1]), 0.1, 500)
    glTranslatef(0, 0, -5)
    button_down = False

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    glTranslatef(-1, 0, 0)
                if event.key == pygame.K_RIGHT:
                    glTranslatef(1, 0, 0)
                if event.key == pygame.K_UP:
                    glTranslatef(0, 1, 0)
                if event.key == pygame.K_DOWN:
                    glTranslatef(0, -1, 0)
            if event.type == pygame.MOUSEMOTION:
                if button_down == True:
                    glRotatef(event.rel[1], 1, 0, 0)
                    glRotatef(event.rel[0], 0, 1, 0)
                print(event.rel)

        for event in pygame.mouse.get_pressed():
            print(pygame.mouse.get_pressed())
            if pygame.mouse.get_pressed()[0] == 1:
                button_down = True
            elif pygame.mouse.get_pressed()[0] == 0:
                button_down = False

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        Cube()
        pygame.display.flip()
        pygame.time.wait(10)

Main()

解决方案

Operations like glTranslated and glRotate define a new matrix and multiply the current matrix by the new matrix.

finalmatrix = matrix1 * matrix2 * matrix3

If you want to apply the operations to the current model transformations than you have to do it in the reverse order.

finalmatrix = matrix3 * matrix2 * matrix1

In Legacy OpenGL, there are different current matrices (see glMatrixMode). The matrices are organized on a stack. The matrices can be pushe on and popped from the stack by glPushMatrix / glPopMatrix. This can be used to save and restore the matrices.

Apply the projection matrix to the projection matrix stack (GL_PROJECTION):

glMatrixMode(GL_PROJECTION)
gluPerspective(45, (screen[0] / screen[1]), 0.1, 500)

Switch to the model view matrix and store the current matrix to a variable modelMatrix at the begin this is the identity matrix:

glMatrixMode(GL_MODELVIEW)  
modelMatrix= glGetFloatv(GL_MODELVIEW_MATRIX)

In the loop:

  • Store the model view matrix and lad the identity matrix:

glPushMatrix()
glLoadIdentity()

  • Do the new transformation (glTranslatef / glRotatef)

  • Multiply the stored model view matrix and get then new final model view matrix

glMultMatrixf(modelMatrix)
modelMatrix= glGetFloatv(GL_MODELVIEW_MATRIX)

  • Load the identity matrix set the view matrix and multiply the model view matrix:

glLoadIdentity()
glTranslatef(0, 0, -5)
glMultMatrixf(modelMatrix)

  • Draw the model and restore the current matrix

Cube()
glPopMatrix()

See the example:

import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *

vertices = ((-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), (1, 2), (1, 5), (2, 3), (2, 6), (3, 7), (4, 5), (4, 7), (5, 6), (6, 7))
faces = ((0, 1, 2 , 3),(4,  5, 6, 7),(0, 4, 7, 3),(1, 5, 6, 2),(2, 6, 7, 3),(1, 5, 4, 0))

# =============================================================================
# vertices = ((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))
# =============================================================================

def Cube():
    glBegin(GL_QUADS)
    for face in faces:
        for vertex in face:
            glColor3fv((1, 0, 1))
            glVertex3fv(vertices[vertex])
    glEnd()

    glBegin(GL_LINES)
    glColor3fv((1, 1, 1))
    for edge in edges:
        for vertex in edge:
            glVertex3fv(vertices[vertex])
    glEnd()

def Main():
    pygame.init()
    screen = (1600, 1200)
    display = pygame.display.set_mode(screen, DOUBLEBUF|OPENGL)
    glMatrixMode(GL_PROJECTION)
    gluPerspective(45, (screen[0] / screen[1]), 0.1, 500)
    button_down = False

    glMatrixMode(GL_MODELVIEW)  
    modelMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)

    while True:
        glPushMatrix()
        glLoadIdentity()

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    glTranslatef(-1, 0, 0)
                if event.key == pygame.K_RIGHT:
                    glTranslatef(1, 0, 0)
                if event.key == pygame.K_UP:
                    glTranslatef(0, 1, 0)
                if event.key == pygame.K_DOWN:
                    glTranslatef(0, -1, 0)
            if event.type == pygame.MOUSEMOTION:
                if button_down == True:
                    glRotatef(event.rel[1], 1, 0, 0)
                    glRotatef(event.rel[0], 0, 1, 0)
                print(event.rel)

        for event in pygame.mouse.get_pressed():
            print(pygame.mouse.get_pressed())
            if pygame.mouse.get_pressed()[0] == 1:
                button_down = True
            elif pygame.mouse.get_pressed()[0] == 0:
                button_down = False

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

        glMultMatrixf(modelMatrix)
        modelMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)

        glLoadIdentity()
        glTranslatef(0, 0, -5)
        glMultMatrixf(modelMatrix)

        Cube()

        glPopMatrix()
        pygame.display.flip()
        pygame.time.wait(10)

Main()

这篇关于如何在pyopengl中使用鼠标旋转立方体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆