如何使用pygame和openGL修改相机的视图 [英] how to modify the view of the camera with pygame and openGL

查看:47
本文介绍了如何使用pygame和openGL修改相机的视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 python3

I'm using python3

我刚刚开始学习 openGL,我需要一些帮助来用鼠标转动您的视图的相机(就像 FPS 游戏一样).现在我的程序看起来像我在移动,但我只是在移动物体,所以如果你能告诉我如何移动相机(向前、向后等),那就太好了.提前致谢

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

我的代码:

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()

推荐答案

对于第一人称运动,必须逐步更改相机矩阵.这意味着您必须计算当前移动和当前旋转矩阵.将移动和旋转应用到相机,并在下一个循环循环中保持相机.在循环的下一个循环中,您必须使用上一个循环中操纵的相机,并且必须应用新的移动和旋转.这会导致相机增量变化,始终基于其当前位置和方向.

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.


在渲染中,场景的每个网格通常由模型矩阵、视图矩阵和投影矩阵进行变换.投影矩阵描述了从场景的 3D 点到视口的 2D 点的映射.视图矩阵描述了观察场景的方向和位置.模型矩阵定义了场景中网格的位置、方向和相对大小.
(参见变换模型矩阵)
在 OpenGL 中,每种矩阵模式都有一个矩阵堆栈(参见 glMatrixMode).矩阵模式为GL_MODELVIEWGL_PROJECTIONGL_TEXTURE.


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.

这意味着您应该在设置投影时使用 GL_PROJECTION 矩阵模式 (gluPerspective):

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 应该使用初始位置进行初始化,您可以通过 glGetFloatv(GL_MODELVIEW_MATRIX, view_mat):

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()

要向左和向右旋转,您必须通过 glRotatef:

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:

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

glGetFloatv(GL_MODELVIEW_MATRIX, view_mat)

在循环开始和结束时,您应该通过 glPushMatrixglPopMatrix.

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)

这篇关于如何使用pygame和openGL修改相机的视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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