how to modify the view of the camera with pygame and openGL

依然范特西╮ 提交于 2020-06-23 08:53:12

问题


I'm using python3

I have just started learning openGL and I need some help turning the camera of your view with a mouse (Like a FPS game). Right now my program looks like i'm moving but i'm just moving the object so if you could tell me how to move the camera(forward, backwards, etc) too that would be nice. Thanks in advance

My Code:

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:


For a first Person movment, the camera matrix has to be incrementally changed. This means you have to calculate the current movement and current rotation matrix. Apply the movement and rotation to the camera and keep the camera for the next cycle of the loop. At the next cycle of the loop you have to use the manipulated camera from the previous cycle and you have to apply the new movement and rotation. This causes that the camera incremental changes, always based on its current position and orientation.


In a rendering, each mesh of the scene usually is transformed by the model matrix, the view matrix and the projection matrix. The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport. The view matrix describes the direction and position from which the scene is looked at. The model matrix defines the location, oriantation and the relative size of a mesh in the scene.
(See Transform the modelMatrix)
In OpenGL there is one matrix stack for each matrix mode (See glMatrixMode). The matrix modes are GL_MODELVIEW, GL_PROJECTION, and GL_TEXTURE.

This means you should use the GL_PROJECTION matrix mode when you set up the projection (gluPerspective):

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

For the first person view matrix you need an variable where you store it:

import numpy

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

view_mat = IdentityMat44()

view_mat should be initilaized with the intial position, you can get the current model matrix by glGetFloatv(GL_MODELVIEW_MATRIX, view_mat):

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

For the rotating to the left and the right you have to perform a rotation around the y-axis by glRotatef:

glRotatef(ry, 0, 1, 0)

To incrementally change the view matrix, you have to do the following:

  • Initialize the view matrix with the identity matrix
  • Apply the new translation and rotation by glTranslatef and glRotatef
  • Transform by the current view matrix glMultMatrixf
  • Store the view matrix for the next cycle 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)

At the beginn an the end of your loop you should push and pop the matrix stack by glPushMatrix and glPopMatrix.


The final function should look somehow like this:

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)


来源:https://stackoverflow.com/questions/47169618/how-to-modify-the-view-of-the-camera-with-pygame-and-opengl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!