当前位置: 首页 > 面试题库 >

如何在PyOpenGL上创建一个可以对鼠标移动进行“透视旋转”的摄像机?

邹山
2023-03-14
问题内容

我正在创建第一人称视角的RPG,并且想在移动鼠标时在PyOpenGL中旋转相机(就像其他游戏一样,如Minecraft)。我可以使用什么功能来执行此操作?

我尝试使用gluLookAt()它,但是尽管经历了不同的来源,但我不知道它是如何工作的。我什至不知道是否能帮上忙。

import sys,pygame
from OpenGL.GL import *
from OpenGL.GLU import *
cmddown = False
#...
keypress = pygame.key.get_pressed()#Move using WASD
    if keypress[pygame.K_w]:
        glTranslatef(0,0,0.1)
    if keypress[pygame.K_s]:
        glTranslatef(0,0,-0.1)
    if keypress[pygame.K_d]:
        glTranslatef(-0.1,0,0)
    if keypress[pygame.K_a]:
        glTranslatef(0.1,0,0)
    mouse_movement = pygame.mouse.get_rel()#Get mouse event
    #This is where the "look around" should be happen
    pygame.display.flip()

问题答案:

您可以使用glRotate绕轴旋转一定量,该量由鼠标的相对移动(pygame.mouse.get_rel())给出:

mouseMove = pygame.mouse.get_rel()
glRotatef(mouseMove[0]*0.1, 0.0, 1.0, 0.0)

但这不会令您满意,因为如果鼠标离开窗口,该解决方案将无法再使用。
您必须将pygame.mouse.set_pos()每一帧的鼠标居中在屏幕中间。通过pygame.MOUSEMOTION事件获取鼠标移动。例如:

# init mouse movement and center mouse on screen
displayCenter = [scree.get_size()[i] // 2 for i in range(2)]
mouseMove = [0, 0]
pygame.mouse.set_pos(displayCenter)

paused = False
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE or event.key == pygame.K_RETURN:
                run = False
            if event.key == pygame.K_PAUSE or event.key == pygame.K_p:
                paused = not paused
                pygame.mouse.set_pos(displayCenter)  
        if event.type == pygame.MOUSEMOTION:
            mouseMove = [event.pos[i] - displayCenter[i] for i in range(2)]
            if not paused:
                pygame.mouse.set_pos(displayCenter)

注意,该操作类似于glRotate
glTranslate设置一个矩阵,然后将当前矩阵乘以新矩阵。

currentMatrix = currentMatrix * newMatrix

这对于模型动画和变换是完美的,但是对于第一人称移动来说,这是错误的方式,在这种情况下,必须更改相机的位置和视角。

viewMatrix = viewTransformMatrix * viewMatrix

做这样的操作glGetFloatv(GL_MODELVIEW_MATRIX)glMultMatrixf。在主循环之前
通过初始化视图矩阵,gluLookAt并通过将视图矩阵加载到html" target="_blank">变量(viewMatrixglGetFloatv(GL_MODELVIEW_MATRIX)

在每个帧的主循环中:

  • 加载身份矩阵(glLoadIdentity
  • 做新的转换到视图(glRotatefglTranslatef
  • 将当前视图矩阵乘以viewMatrixglMultMatrixf
  • 将新的视图矩阵加载到viewMatrix下一帧

    glMatrixMode(GL_MODELVIEW)
    gluLookAt(0, -8, 0, 0, 0, 0, 0, 0, 1)
    viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
    glLoadIdentity()

    run = True
    while run:

    # [...]
    
    # init the view matrix
    glLoadIdentity()
    
    # apply the movment 
    if keypress[pygame.K_w]:
        glTranslatef(0,0,0.1)
    if keypress[pygame.K_s]:
        glTranslatef(0,0,-0.1)
    if keypress[pygame.K_d]:
        glTranslatef(-0.1,0,0)
    if keypress[pygame.K_a]:
        glTranslatef(0.1,0,0)
    
    # apply the roation
    glRotatef(mouseMove[0]*0.1, 0.0, 1.0, 0.0)
    
    # multiply the current matrix by the get the new view matrix and store the final vie matrix 
    glMultMatrixf(viewMatrix)
    viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
    

为了向上和向下查找,您必须绕x轴进行最终旋转。旋转的枢轴取决于角度。必须对角度进行求和,并且必须在视图矩阵之后应用旋转,否则运动会根据角度改变(“高度”)水平。

viewMatrix = viewTransformMatrix * viewMatrix
finlalMatrix = lookUpDownMatrix * viewMatrix

为此,您必须汇总上下旋转矩阵并将其乘以 viewMatrix

up_down_angle = 0.0
run = True
while run:

    # [...]

    # init model view matrix
    glLoadIdentity()

    # apply the look up and down
    up_down_angle += mouseMove[1]*0.1
    glRotatef(up_down_angle, 1.0, 0.0, 0.0)

    # init the view matrix
    glPushMatrix()
    glLoadIdentity()

    # calculate new `viewMatrix` 
    # [...]

    # apply view matrix
    glPopMatrix()
    glMultMatrixf(viewMatrix)

请参见以下示例程序,该程序演示了该过程。
请注意,该程序 将鼠标保持在 窗口 的中央 ,因此您不能再“移动”鼠标。因此, 可以通过ESC或停止return应用程序。
可以 通过pause或暂停p应用程序。暂停应用程序时, 鼠标不会居中 于窗口。

import pygame
from pygame.locals import *

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

import math

pygame.init()
display = (400, 300)
scree = pygame.display.set_mode(display, DOUBLEBUF | OPENGL)

glEnable(GL_DEPTH_TEST)
glEnable(GL_LIGHTING)
glShadeModel(GL_SMOOTH)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)

glEnable(GL_LIGHT0)
glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5, 1])
glLightfv(GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1])

sphere = gluNewQuadric()

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

glMatrixMode(GL_MODELVIEW)
gluLookAt(0, -8, 0, 0, 0, 0, 0, 0, 1)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
glLoadIdentity()

# init mouse movement and center mouse on screen
displayCenter = [scree.get_size()[i] // 2 for i in range(2)]
mouseMove = [0, 0]
pygame.mouse.set_pos(displayCenter)

up_down_angle = 0.0
paused = False
run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE or event.key == pygame.K_RETURN:
                run = False
            if event.key == pygame.K_PAUSE or event.key == pygame.K_p:
                paused = not paused
                pygame.mouse.set_pos(displayCenter) 
        if not paused: 
            if event.type == pygame.MOUSEMOTION:
                mouseMove = [event.pos[i] - displayCenter[i] for i in range(2)]
            pygame.mouse.set_pos(displayCenter)

    if not paused:
        # get keys
        keypress = pygame.key.get_pressed()
        #mouseMove = pygame.mouse.get_rel()

        # init model view matrix
        glLoadIdentity()

        # apply the look up and down
        up_down_angle += mouseMove[1]*0.1
        glRotatef(up_down_angle, 1.0, 0.0, 0.0)

        # init the view matrix
        glPushMatrix()
        glLoadIdentity()

        # apply the movment 
        if keypress[pygame.K_w]:
            glTranslatef(0,0,0.1)
        if keypress[pygame.K_s]:
            glTranslatef(0,0,-0.1)
        if keypress[pygame.K_d]:
            glTranslatef(-0.1,0,0)
        if keypress[pygame.K_a]:
            glTranslatef(0.1,0,0)

        # apply the left and right rotation
        glRotatef(mouseMove[0]*0.1, 0.0, 1.0, 0.0)

        # multiply the current matrix by the get the new view matrix and store the final vie matrix 
        glMultMatrixf(viewMatrix)
        viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)

        # apply view matrix
        glPopMatrix()
        glMultMatrixf(viewMatrix)

        glLightfv(GL_LIGHT0, GL_POSITION, [1, -1, 1, 0])

        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)

        glPushMatrix()

        glColor4f(0.5, 0.5, 0.5, 1)
        glBegin(GL_QUADS)
        glVertex3f(-10, -10, -2)
        glVertex3f(10, -10, -2)
        glVertex3f(10, 10, -2)
        glVertex3f(-10, 10, -2)
        glEnd()

        glTranslatef(-1.5, 0, 0)
        glColor4f(0.5, 0.2, 0.2, 1)
        gluSphere(sphere, 1.0, 32, 16)

        glTranslatef(3, 0, 0)
        glColor4f(0.2, 0.2, 0.5, 1)
        gluSphere(sphere, 1.0, 32, 16)

        glPopMatrix()

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

pygame.quit()


 类似资料:
  • 问题内容: 我正在从事类似于UBER,Lyft或OLA的项目。使用可用的移动汽车在家里进行地图。我正在寻找某种图书馆,可以像UBER一样使汽车平稳行驶和转弯。现在,我可以使用以下代码将汽车平稳地从一个纬度移动到另一个纬度。但是棘手的部分是转弯,并确保汽车在转向时朝前。 平稳行驶的汽车代码: 问题答案: 我最近遇到了相同的用例。这是我的解决方案。 首先,我要感谢@VipiN分享了“ The Movi

  • 我正在尝试创建一个圆形进度条。这就是我想要实现的 有一个灰色的背景环。在它的顶部,会出现一个蓝色的进度条,它在60秒内或任何时间内以圆形路径从0移动到360。 这是我的示例代码。 为此,在可绘制的“progressBarBG”中,我创建了一个层列表,在该层列表中,我给出了两个项目,如图所示。 现在,第一个灰色环生成良好。然而,蓝环从可绘制的左侧开始,然后向右移动,就像线性进度条一样。这是它以50%

  • 我目前有一个游戏,有一个地图是480x3200,一个人从顶部掉下来。镜头跟在人的后面,随着人的下落有平台。平台需要是可触摸的,所以我可以在游戏中旋转和移动它们,所以我把它变成了一个图像,而它原本只是一个精灵。 编辑:

  • 问题内容: 我正在尝试用Python创建Rubik’s Cube,我已经从视觉上表示了这个立方体。如何实施轮换方面有些困难。 我想我正在寻求有关如何执行此操作的反馈。我首先想到的是旋转每个立方体的一组顶点,但是运气不好。 我基本上想从一组多维数据集对象(大小不一)中选择一个切片,对每个对象执行旋转和平移。 我希望对此有更多了解的人可以为我提供一些有关如何进行的指导。 问题答案: 魔方可以通过 3x

  • 问题内容: 在张量流中,我想从随机角度旋转图像,以进行数据增强。但是我在tf.image模块中找不到这种转换。 问题答案: 更新 :请参阅下面的@astromme答案。Tensorflow现在支持本地旋转图像。 在Tensorflow中没有本机方法的情况下可以执行的操作是这样的:

  • 问题内容: Java Swing问题。 我有一个显示图表。当我将鼠标移到该图上时,我希望某些信息显示在随鼠标移动的类似工具提示的小部件上。我怎样才能最好地实现这一目标? 我想如果我知道如何在作为我的绘图画布的绝对位置内放置一个自定义项,就可以解决我的问题。然后,我可以捕获鼠标移动的事件并重新定位/更新小部件。任何其他解决方案(包括可能直接使用)也将非常受欢迎! 问题答案: 覆盖根据鼠标位置动态设置

  • 我正在尝试围绕我的模型旋转我的透视相机。模型位于中心(0,0,0)点。这是我的旋转相机方法: 我试着去中心,旋转5度,然后回到同样的距离。然而,旋转似乎不起作用,我不知道为什么,任何帮助都非常感谢。

  • 我是新来发帖的,所以请友善些!我已经研究了几乎所有其他与此相关的问题,并尝试了大多数,但我完全感到沮丧。我只想让我的Android手机以纵向模式显示摄像头,而不是横向模式。我只是修改opencv提供的ImageManipulations示例。 我使用的是opencv 3.01、Android sdk版本23、Android Studio 2.0和Android版本6.0.1的Nexus 5手机。这