尝试在我的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()
任何帮助将不胜感激!
答案 0 :(得分: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库,它已经编写了许多此类任务,因此您可以使用该库本身,也可以打开该库的代码以从内部了解一切。