我正在使用OpenGL和Pygame制作游戏。到目前为止,我已经能够使立方体出现并制作十字准线。当我尝试实施环顾四周时,事情变得...很奇怪。我将运行它,甚至不动鼠标,当我使用compact
函数时,它将开始在任何地方旋转屏幕。当我取出来时,它奏效了,但我看不到周围。我正在做一些测试,甚至将设置数据值放到函数中,以确保它们没有改变并且仍然旋转。我完全感到困惑,对OpenGL还是陌生的,而且我还不到两个月的时间来完成我的项目。预先感谢您提供的所有帮助,这是我的代码:My code on GitHub
我正在使用python 3.6 btw。
答案 0 :(得分:2)
在您的代码中有2个问题。
gluLookAt
设置视图矩阵。但这并不是全部。
gluLookAt
将视图矩阵乘以矩阵堆栈上的当前矩阵,该矩阵由glMatrixMode
选择。在致电gluLookAt
来解决此问题之前,请设置[身份矩阵]。这导致模型视图矩阵是从头开始设置的,而与它以前的状态无关。
glLoadIdentity()
gluLookAt(0, 0, 0, facing[0], facing[1], lookingZ, 0, 1, 0)
这不能完全解决您的问题,因为在设置视图矩阵时,模型视图矩阵堆栈上的当前矩阵就是投影矩阵和视图矩阵的串联。这导致glLoadIdentity
也跳过了投影矩阵。
此行为可以轻松解决。将视图矩阵放在模型视图矩阵堆栈(GL_MODELVIEW
)上,并将投影矩阵放在投影矩阵堆栈(GL_PROJECTION
)上:
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (width/height), 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
一个更好且完全可行的解决方案是将围绕x和y轴的旋转矩阵应用于视图矩阵。首先应用绕y轴(向上矢量)的旋转矩阵,然后应用当前视图矩阵,最后应用沿x轴的旋转:
view-matrix = rotate-X * view-matrix * rotate-Y
为此,当前视图矩阵必须由glGetFloatv(GL_MODELVIEW_MATRIX)
读取:
modelview = glGetFloatv(GL_MODELVIEW_MATRIX)
glLoadIdentity()
glRotate(-change[1]*0.1, 1, 0, 0)
glMultMatrixf(modelview)
glRotate(change[0]*0.1, 0, 1, 0)
请注意,此操作必须代替:
glLoadIdentity()
gluLookAt(0, 0, 0, facing[0], facing[1], lookingZ, 0, 1, 0)
完成main
函数(renderingEngine.py),并建议更改:
def main(world,x,y,z,width,height,renderDistance):
pygame.init()
pygame.display.set_mode((width,height), DOUBLEBUF | OPENGL)
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glDepthMask(GL_TRUE)
glDepthFunc(GL_LESS)
glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glCullFace(GL_BACK)
glFrontFace(GL_CCW)
glShadeModel(GL_SMOOTH)
glDepthRange(0.0, 1.0)
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (width/height), 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
#pygame.mouse.set_visible(False)
facing = [0, 0, False]
while True:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_a:
pygame.mouse.set_visible(True)
pygame.quit()
return # TODO: Add pause
newMousePos = pygame.mouse.get_pos()
change = (newMousePos[0]-(width/2), newMousePos[1]-(height/2))
pygame.mouse.set_pos([width / 2, height / 2])
if facing[2]:
facing[0] -= change[0]
else:
facing[0] += change[0]
facing[1] += change[1]
while facing[0] > width:
facing[0] = 2*width-facing[0]
facing[2] = not facing[2]
while facing[0] < 0:
facing[0] = 0-facing[0]
facing[2] = not facing[2]
if facing[1] < 0:
facing[1] = 0
if facing[1] > height:
facing[1] = height
radius = (width**2+height**2)**.5+1
lookingZ = (-1*facing[0]**2-facing[1]**2+radius**2)**.5
if facing[2]:
lookingZ *= -1
#print(lookingZ, facing[0], facing[1], radius)
print(facing[0], facing[1], lookingZ)
#glLoadIdentity()
#gluLookAt(0, 0, 0, facing[0], facing[1], lookingZ, 0, 1, 0)
modelview = glGetFloatv(GL_MODELVIEW_MATRIX)
glLoadIdentity()
glRotate(-change[1]*0.1, 1, 0, 0)
glMultMatrixf(modelview)
glRotate(change[0]*0.1, 0, 1, 0)
xmin = round(x-renderDistance[0])
ymin = round(y-renderDistance[1])
zmin = round(z-renderDistance[2])
if xmin < 0:
xmin = 0
if ymin < 0:
ymin = 0
if zmin < 0:
zmin = 0
xmax = round(x+renderDistance[0])
ymax = round(y+renderDistance[1])
zmax = round(z+renderDistance[2])
dims = world.dims()
if xmax > dims[0]:
xmax = dims[0]
if ymax > dims[1]:
ymax = dims[1]
if zmax > dims[2]:
zmax = dims[2]
selection = world.select_data(xrange = (xmin, xmax), yrange = (ymin, ymax), zrange = (zmin, zmax))
blocks = selection.iterate(ignore=(None,))
glClearDepth(1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
for bl in blocks:
locations = bl[0]
block = bl[1]
cube(locations[0] - x, locations[1] - y, locations[2] - z, block)
#print(locations[0],locations[1],locations[2])
glMatrixMode(GL_PROJECTION)
glPushMatrix()
glLoadIdentity()
glOrtho(0.0, width, 0.0, height, -1.0, 1.0)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()
glLoadIdentity()
glDisable(GL_DEPTH_TEST)
crosshair(width/2, height/2, 20)
glEnable(GL_DEPTH_TEST)
glMatrixMode(GL_PROJECTION)
glPopMatrix()
glMatrixMode(GL_MODELVIEW)
glPopMatrix()
glCullFace(GL_BACK)
pygame.display.flip()
time.sleep(.01)