Использование gluLookAt () заставляет объекты вращаться - PullRequest
0 голосов
/ 23 января 2019

Я делаю игру, используя OpenGL с Pygame.До сих пор мне удавалось создавать кубики и делать перекрестие.Когда я попытался осмотреться, все стало ... странно.Я запускал его, и даже не двигая мышью, он начинал вращать экран повсюду, когда я использовал функцию gluLookAt().Когда я взял это, это сработало, но я не мог смотреть вокруг.Я проводил некоторое тестирование и даже вставил в функцию установленные значения данных, чтобы убедиться, что они не меняются и все еще вращаются.Я полностью озадачен, и я новичок в OpenGL, и у меня есть меньше двух месяцев, чтобы закончить свой проект.Заранее благодарю за то, что вы можете мне помочь, и вот мой код: Мой код на GitHub

Я на Python 3.6 между прочим.

1 Ответ

0 голосов
/ 25 января 2019

В вашем коде есть 2 проблемы.

  1. gluLookAt устанавливает матрицу просмотра.Но это еще не все.gluLookAt умножает матрицу вида на текущую матрицу в стеке матриц, которую выбирает glMatrixMode.
    Таким образом, ваш код объединяет новую матрицу вида с существующей матрицей представления.Это приводит к тому, что объекты начинают быстро вращаться.

Установите Identity matrix перед вызовом 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 ( renderEngine.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)
...