使用 gluLookAt() 会导致对象旋转 [英] Using gluLookAt() causes the objects to spin

查看:47
本文介绍了使用 gluLookAt() 会导致对象旋转的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 OpenGL 和 Pygame 制作游戏.到目前为止,我能够使立方体出现并制作十字准线.当我试图实现环顾四周时,事情变得......很奇怪.当我使用 gluLookAt() 函数时,我会运行它,甚至不用移动鼠标,它就会开始到处旋转屏幕.当我把它拿出来时,它起作用了,但我无法环顾四周.我正在做一些测试,我什至在函数中设置了数据值,只是为了确保它们没有改变并且它仍然在旋转.在此先感谢您提供的任何帮助,这是我的代码:

一个更好且完全有效的解决方案是将围绕 x 和 y 轴的旋转矩阵应用于视图矩阵.首先应用绕 y 轴(向上向量)的旋转矩阵,然后应用当前视图矩阵,最后应用绕 x 轴的旋转:

view-matrix = rotate-X * view-matrix * rotate-Y

为此,必须通过

完成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, (宽/高), 0.1, 100.0)glMatrixMode(GL_MODELVIEW)glPushMatrix()#pygame.mouse.set_visible(False)面对 = [0, 0, 假]为真:对于 pygame.event.get() 中的事件:如果 event.type == pygame.KEYDOWN:如果 event.key == pygame.K_a:pygame.mouse.set_visible(真)pygame.quit()return # TODO: 添加暂停newMousePos = pygame.mouse.get_pos()更改 = (newMousePos[0]-(width/2), newMousePos[1]-(height/2))pygame.mouse.set_pos([宽/2,高/2])如果面对[2]:面对[0] -= 改变[0]别的:面对[0] += 改变[0]面对[1] += 改变[1]而面对[0] >宽度:面向[0] = 2*面向宽度[0]面对[2] = 不面对[2]当面对[0] <0:面对[0] = 0面对[0]面对[2] = 不面对[2]如果面对[1] <0:面对[1] = 0如果面对[1] >高度:面对[1] = 高度半径 = (宽**2+高**2)**.5+1看Z = (-1*面[0]**2-面[1]**2+半径**2)**.5如果面对[2]:看Z *= -1#打印(看Z,面对[0],面对[1],半径)打印(面对[0],面对[1],看Z)#glLoadIdentity()#gluLookAt(0, 0, 0, 面[0], 面[1], 看Z, 0, 1, 0)模型视图 = glGetFloatv(GL_MODELVIEW_MATRIX)glLoadIdentity()glRotate(-change[1]*0.1, 1, 0, 0)glMultMatrixf(模型视图)glRotate(change[0]*0.1, 0, 1, 0)xmin = round(x-renderDistance[0])ymin = round(y-renderDistance[1])zmin = round(z-renderDistance[2])如果 xmin <0:最小 = 0如果 ymin <0:ymin = 0如果 zmin <0:zmin = 0xmax = round(x+renderDistance[0])ymax = round(y+renderDistance[1])zmax = round(z+renderDistance[2])昏暗 = world.dims()如果 xmax >暗淡[0]:xmax = 暗淡[0]如果 ymax >暗淡[1]:ymax = 暗淡 [1]如果 zmax >暗淡[2]:zmax = 暗淡[2]selection = world.select_data(xrange = (xmin, xmax), yrange = (ymin, ymax), zrange = (zmin, zmax))块 = selection.iterate(ignore=(None,))glClearDepth(1.0)glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)对于块中的 bl:位置 = bl[0]块 = bl[1]立方体(位置[0] - x,位置[1] - y,位置[2] - z,块)#print(位置[0],位置[1],位置[2])glMatrixMode(GL_PROJECTION)glPushMatrix()glLoadIdentity()glOrtho(0.0, 宽度, 0.0, 高度, -1.0, 1.0)glMatrixMode(GL_MODELVIEW)glPushMatrix()glLoadIdentity()glDisable(GL_DEPTH_TEST)十字准线(宽/2,高/2,20)glEnable(GL_DEPTH_TEST)glMatrixMode(GL_PROJECTION)glPopMatrix()glMatrixMode(GL_MODELVIEW)glPopMatrix()glCullFace(GL_BACK)pygame.display.flip()时间.睡眠(.01)

I am making a game using OpenGL with Pygame. So far I was able to make cubes appear and make a cross hair. When I tried to implement looking around, things got... weird. I would run it and without even moving my mouse it would start spinning the screen everywhere when I used the gluLookAt() function. When I took that out, it worked but I couldn't look around. I was doing some testing and I even put in set data values to the function just to make sure that they were not changing and it still spun. Thanks in advance for whatever you are able to help me with and here is my code: My code on GitHub

解决方案

In your code there are 2 issues.

  1. gluLookAt sets up a view matrix. But this is not all. gluLookAt multiplies the view matrix to the current matrix on the matrix stack, which is chosen by glMatrixMode.
    So your code concatenates the new view matrix to the existing view matrix. This causes that the objects start to spin rapidly.

Set the Identity matrix before you call gluLookAt to solve this issue. This causes that the model view matrix is set from scratch, independent on its former state.

glLoadIdentity()
gluLookAt(0, 0, 0, facing[0], facing[1], lookingZ, 0, 1, 0)

  1. This won't solve you issue completely, because at the point when you set the view matrix, then current matrix on the model view matrix stack is the concatenation of the projection matirx and the view matrix. This cause the glLoadIdentity also skips the projection matrix.
    This behaviour can be solved with ease. Put the view matrix on the model view matrix stack (GL_MODELVIEW) and the projection matrix to the projection matrix stack (GL_PROJECTION):

glMatrixMode(GL_PROJECTION)
gluPerspective(45, (width/height), 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)
glPushMatrix()

An much better and completely working solution is to apply a rotation matrix around the x and y axis to the view matrix. First apply the rotation matrix around the y axis (up vector) then the current view matrix and finally the rotation on the x axis:

view-matrix = rotate-X * view-matrix * rotate-Y

For this the current view matrix has to be read by 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)

Note, this has to be done instead of:

glLoadIdentity()
gluLookAt(0, 0, 0, facing[0], facing[1], lookingZ, 0, 1, 0)

Complete main function (renderingEngine.py), with the suggested changes:

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)

这篇关于使用 gluLookAt() 会导致对象旋转的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆