Как изменить вид камеры с помощью pygame и openGL

Я использую python3

Я только начал изучать openGL, и мне нужна помощь, чтобы повернуть камеру вашего взгляда с помощью мыши (как в игре FPS). Прямо сейчас моя программа выглядит так, как будто я двигаюсь, но я просто двигаю объект, поэтому, если бы вы могли сказать мне, как перемещать камеру (вперед, назад и т. Д.), Это было бы неплохо. заранее спасибо

Мой код:

import pygame
from pygame.locals import *

from OpenGL.GL import *
from OpenGL.GLU import *



vertices = (
    (1, -1, -1),
    (1, 1, -1),
    (-1, 1, -1),
    (-1, -1, -1),
    (1, -1, 1),
    (1, 1, 1, ),
    (-1, -1, 1),
    (-1, 1, 1),
    )

edges = (
    (0,1),
    (0,3),
    (0,4),
    (2,1),
    (2,3),
    (2,7),
    (6,3),
    (6,4),
    (6,7),
    (5,1),
    (5,4),
    (5,7),
    )

surfaces = (
    (0,1,2,3),
    (3,2,7,6),
    (6,7,5,4),
    (4,5,1,0),
    (1,5,7,2),
    (4,0,3,6),
    )

colors = (
    (1,1,1),
    (0,0,0),
    (0,1,1),
    (0,0,0),
    (0,1,1),
    (1,0,1),
    (0,0,0),
    (1,1,1),
    (0,0,0),
    (0,1,1),
    )

def Cube():
    glBegin(GL_QUADS)


    for surface in surfaces:
        x = 0

        for vertex in surface:
            x += 1
            glColor3fv(colors[x])
            glVertex3fv(vertices[vertex])


    glEnd()

    glBegin(GL_LINES)
    for edge in edges:
        for vertex in edge:
            glVertex3fv(vertices[vertex])

    glEnd()


def main():
    pygame.init()
    x = 0
    y = 0
    z = 0
    display = (800,600)
    pygame.display.set_mode(display, DOUBLEBUF|OPENGL|RESIZABLE)
    pygame.event.set_grab(True)
    pygame.mouse.set_visible( False )


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

    glTranslatef(0, 0, -5)

    glRotatef(0, 0, 0, 0)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                quit()

            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    quit()

                if event.key == pygame.K_a:
                    x = 0.1

                elif event.key == pygame.K_d:
                    x = -0.1

                elif event.key == pygame.K_w:
                    z = 0.1

                elif event.key == pygame.K_s:
                    z = -0.1

            elif event.type == pygame.KEYUP:

                if event.key == pygame.K_a and x > 0:
                    x = 0

                elif event.key == pygame.K_d and x < 0:
                    x = 0

                if event.key == pygame.K_w and z > 0:
                    z = 0

                if event.key == pygame.K_s and z < 0:
                    z = 0

        glTranslatef(x,y,z)

        #glRotatef(1, 2, 3, 4)
        glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
        Cube()
        pygame.display.flip()
        pygame.time.wait(10)
main()

1 ответ

Решение

Для движения от первого лица матрица камеры должна изменяться постепенно. Это означает, что вы должны рассчитать текущее движение и текущую матрицу вращения. Примените движение и вращение к камере и удерживайте камеру для следующего цикла цикла. На следующем цикле цикла вы должны использовать управляемую камеру из предыдущего цикла, и вы должны применить новое движение и вращение. Это приводит к тому, что камера постепенно изменяется, всегда основываясь на ее текущем положении и ориентации.


При рендеринге каждая сетка сцены обычно преобразуется матрицей модели, матрицей вида и матрицей проекции. Матрица проекции описывает отображение от трехмерных точек сцены к двухмерным точкам области просмотра. Матрица вида описывает направление и позицию, с которой просматривается сцена. Матрица модели определяет местоположение, ориентацию и относительный размер сетки в сцене.
(См. Преобразование модели Matrix)
В OpenGL есть один стек матрицы для каждого режима матрицы (см. glMatrixMode). Матричные режимы GL_MODELVIEW, GL_PROJECTION, а также GL_TEXTURE,

Это означает, что вы должны использовать GL_PROJECTION матричный режим при настройке проекции (gluPerspective):

glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

Для матрицы вида от первого лица вам нужна переменная, в которой вы ее храните:

import numpy

def IdentityMat44(): return numpy.matrix(numpy.identity(4), copy=False, dtype='float32')

view_mat = IdentityMat44()

view_mat следует инициализировать с начальной позиции, вы можете получить текущую модель матрицы glGetFloatv(GL_MODELVIEW_MATRIX, view_mat):

glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(0, 0, -5)
glGetFloatv(GL_MODELVIEW_MATRIX, view_mat)
glLoadIdentity()

Для поворота влево и вправо вы должны выполнить вращение вокруг оси Y на glRotatef:

glRotatef(ry, 0, 1, 0)

Чтобы постепенно изменить матрицу представления, вы должны сделать следующее:

  • Инициализируйте матрицу представления с помощью матрицы тождественности
  • Применить новый перевод и вращение glTranslatef а также glRotatef
  • Преобразовать с помощью матрицы текущего представления glMultMatrixf
  • Сохранить матрицу просмотра для следующего цикла glGetFloatv(GL_MODELVIEW_MATRIX, view_mat)

glLoadIdentity()
glTranslatef(tx,ty,tz)
glRotatef(ry, 0, 1, 0)
glMultMatrixf(view_mat)

glGetFloatv(GL_MODELVIEW_MATRIX, view_mat)

В начале и конце вашего цикла вы должны нажать и вытолкнуть стек матрицы glPushMatrix а также glPopMatrix,


Последняя функция должна выглядеть примерно так:

tx = 0
ty = 0
tz = 0
ry = 0

glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)

view_mat = IdentityMat44()
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
glTranslatef(0, 0, -5)
glGetFloatv(GL_MODELVIEW_MATRIX, view_mat)
glLoadIdentity()

while True:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                quit()
            if   event.key == pygame.K_a:     tx =  0.1
            elif event.key == pygame.K_d:     tx = -0.1
            elif event.key == pygame.K_w:     tz =  0.1
            elif event.key == pygame.K_s:     tz = -0.1
            elif event.key == pygame.K_RIGHT: ry =  1.0
            elif event.key == pygame.K_LEFT:  ry = -1.0
        elif event.type == pygame.KEYUP: 
            if   event.key == pygame.K_a     and tx > 0: tx = 0
            elif event.key == pygame.K_d     and tx < 0: tx = 0
            elif event.key == pygame.K_w     and tz > 0: tz = 0
            elif event.key == pygame.K_s     and tz < 0: tz = 0
            elif event.key == pygame.K_RIGHT and ry > 0: ry = 0.0
            elif event.key == pygame.K_LEFT  and ry < 0: ry = 0.0

    glPushMatrix()
    glLoadIdentity()
    glTranslatef(tx,ty,tz)
    glRotatef(ry, 0, 1, 0)
    glMultMatrixf(view_mat)

    glGetFloatv(GL_MODELVIEW_MATRIX, view_mat)

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
    Cube()
    glPopMatrix()

    pygame.display.flip()
    pygame.time.wait(10)
Другие вопросы по тегам