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

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

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

您可以使用

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 screendisplayCenter = [scree.get_size()[i] // 2 for i in range(2)]mouseMove = [0, 0]pygame.mouse.set_pos(displayCenter)paused = Falserun = Truewhile 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
并通过将视图矩阵加载到变量(
viewMatrix
glGetFloatv(GL_MODELVIEW_MATRIX)

在每个帧的主循环中:

  • 加载身份矩阵(
    glLoadIdentity
  • 做新的转换到视图(
    glRotatef
    glTranslatef
  • 将当前视图矩阵乘以
    viewMatrix
    glMultMatrixf
  • 将新的视图矩阵加载到

    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 matrixglLoadIdentity()# 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 roationglRotatef(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 * viewMatrixfinlalMatrix = lookUpDownMatrix * viewMatrix

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

viewMatrix

up_down_angle = 0.0run = Truewhile 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 pygamefrom pygame.locals import *from OpenGL.GL import *from OpenGL.GLU import *import mathpygame.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 screendisplayCenter = [scree.get_size()[i] // 2 for i in range(2)]mouseMove = [0, 0]pygame.mouse.set_pos(displayCenter)up_down_angle = 0.0paused = Falserun = Truewhile 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()


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5674636.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存