我如何成功处理OpenGL的gluLookAt功能?

问题描述 投票:0回答:1

尝试在我的python和pygame 3D OpenGL游戏中实现3D漫游相机是我一直想做的事情,但是遇到了障碍。每次我尝试使用gluLookAt函数时,相机都会摇晃并晃动,而x和z坐标会迅速增加,并从负变为正。我尝试制作的游戏只是您在周围走来走去的平面。我已经实现了所有用于移动的控件,但没有实现照相机。

以下是一些摘要代码,适合那些不想阅读我所有代码的人:

while True:
    matrix = glGetDoublev(GL_MODELVIEW_MATRIX)
    camera_x = matrix[3][0]
    camera_y = matrix[3][1]
    camera_z = matrix[3][2]

    # the 3-6 ones are what the camera is looking at
    gluLookAt(camera_x, camera_y, camera_z, 0, 0, 0, 0, 1, 0)
    print("({}, {}, {})".format(int(-camera_x), int(-camera_y), int(-camera_z)))

如果上述代码无法解决问题,请使用我的完整(ish)代码:

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

speed = .5

def enviroment():
    glBegin(GL_QUADS)
    for surface in surfaces:
        for vertex in surface:
            glColor3fv((1, 0, 0))
            glVertex3fv(verticies[vertex])
    glEnd()

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


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

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

    glTranslatef(0.0, -3, -150)

    glRotatef(0, 0, 0, 0)

    while True:
        press = pygame.key.get_pressed()

        matrix = glGetDoublev(GL_MODELVIEW_MATRIX)
        camera_x = matrix[3][0]
        camera_y = matrix[3][1]
        camera_z = matrix[3][2]

        # the 3-6 ones are what the camera is looking at
        gluLookAt(camera_x, camera_y, camera_z, 0, 0, 0, 0, 1, 0)

        print("({}, {}, {})".format(int(-camera_x), int(-camera_y), int(-camera_z)))

        if press[pygame.K_UP]:
            glTranslatef(0, -speed, 0)
        elif press[pygame.K_DOWN]:
            glTranslatef(0, speed, 0)

        elif press[pygame.K_w]:
            glTranslatef(0, 0, speed)
        elif press[pygame.K_s]:
            glTranslatef(0, 0, -speed)
        elif press[pygame.K_a]:
            glTranslatef(speed, 0, 0)
        elif press[pygame.K_d]:
            glTranslatef(-speed, 0, 0)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()
            elif event.type == KEYDOWN:
                if event.key == K_UP:
                    glTranslatef(0, -speed, 0)
                elif event.key == K_DOWN:
                    glTranslatef(0, speed, 0)

                elif event.key == K_w:
                    glTranslatef(0, 0, speed)
                elif event.key == K_s:
                    glTranslatef(0, 0, -speed)

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

main()

任何帮助将不胜感激!

python opengl 3d pygame glulookat
1个回答
0
投票

首先,我不知道您使用pygame的原因。 OpenGL和GLUT(OpenGL实用工具包)的组合几乎包含了3D图形所需的所有功能(尤其是在初学者的水平)。因此,如果您要开始使用3D图形-GLUT几乎是您所需要的一切。

关于gluLookAt功能:该函数本身具有9个参数,如果要控制摄像机的位置-您需要使用前三个参数进行操作:

gluLookAt(eyeX, eyeY, eyeZ, ...)

要围绕对象(位于0、0、0的位置)旋转相机,您需要更改eyeX,eyeY和eyeZ,以便它们的平方和为1(或其他值,具体取决于距离相机应该是的对象):

eyeX^2 + eyeY^2 + eyeZ^2 = 1

需要满足,因为这是3D球体的方程。

开始时,您可以将eyeY变量设置为0,以便摄像机仅在围绕对象的平面内旋转。然后我们需要满足以下声明:

eyeX^2 + eyeZ^2 = 1

这是球体到2D-圆的投影的等式

让我们介绍一个角度α,它将代表相机的位置。为了控制相机围绕物体旋转的方式,我们将更改此角度。

Angle image (the image is viewed from above)

所以现在,我们需要将此角度转换为坐标,以便在OpenGL函数中使用。

这可以使用三角函数来完成。 Sin(α)将代表我们的Z轴值,Cos(α)-我们的X轴值。此代码会将我们的角度转换为坐标:

eyeZ = math.sin(alpha)
eyeX = math.cos(alpha)

所以现在我们只需要使用gluLookAt函数:

gluLookAt(eyeX, 0, eyeZ, 0, 0, 0, 0, 1, 0)

要移动相机,您需要以自己喜欢的任何方式更改α角度。

要进行更复杂的摄影机管理,您将需要解决的不是圆弧相等,而是球面相等,并使用两个角度而不是一个角度。

这是一项艰巨的任务,但是我建议您看一下TRON项目(https://github.com/leviathan117/TRON/)。这是一个面向初学者的3D图形Python库,并且已经编写了许多此类任务,因此您可以使用该库本身,也可以打开该库的代码以从内部查看一切工作。

© www.soinside.com 2019 - 2024. All rights reserved.