您可以使用glRotate https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRotate.xml绕轴旋转,旋转量由相对鼠标移动给出(pygame.mouse.get_rel() https://www.pygame.org/docs/ref/mouse.html#pygame.mouse.get_focused):
mouseMove = pygame.mouse.get_rel()
glRotatef(mouseMove[0]*0.1, 0.0, 1.0, 0.0)
但这不会让您满意,因为如果鼠标离开窗口,该解决方案将不再起作用。
您必须将鼠标置于屏幕中央pygame.mouse.set_pos() https://www.pygame.org/docs/ref/mouse.html#pygame.mouse.set_pos在每一帧中。通过以下方式获取鼠标移动pygame.MOUSEMOTION https://www.pygame.org/docs/ref/event.html事件。例如。:
# init mouse movement and center mouse on screen
displayCenter = [scree.get_size()[i] // 2 for i in range(2)]
mouseMove = [0, 0]
pygame.mouse.set_pos(displayCenter)
paused = False
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE or event.key == pygame.K_RETURN:
run = False
if event.key == pygame.K_PAUSE or event.key == pygame.K_p:
paused = not paused
pygame.mouse.set_pos(displayCenter)
if event.type == pygame.MOUSEMOTION:
mouseMove = [event.pos[i] - displayCenter[i] for i in range(2)]
if not paused:
pygame.mouse.set_pos(displayCenter)
请注意,像这样的操作glRotate https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glRotate.xml and glTranslate https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glTranslate.xml设置一个矩阵并将当前矩阵乘以新矩阵。
currentMatrix = currentMatrix * newMatrix
这对于模型动画和转换来说是完美的,但对于第一人称移动来说这是错误的方式,因为必须改变相机位置和视角。
viewMatrix = viewTransformMatrix * viewMatrix
进行这样的操作glGetFloatv(GL_MODELVIEW_MATRIX) https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glGet.xml and glMultMatrixf https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glMultMatrix.xml.
初始化视图矩阵gluLookAt https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/gluLookAt.xml并将视图矩阵加载到变量(viewMatrix
) by glGetFloatv(GL_MODELVIEW_MATRIX)
,在主循环之前。
在每一帧的主循环中:
- 加载单位矩阵 https://en.wikipedia.org/wiki/Identity_matrix (glLoadIdentity https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glLoadIdentity.xml)
- 对视图进行新的转换(
glRotatef
, glTranslatef
)
- 将当前视图矩阵乘以
viewMatrix
(glMultMatrixf
)
- 将新的视图矩阵加载到
viewMatrix
对于下一帧
glMatrixMode(GL_MODELVIEW)
gluLookAt(0, -8, 0, 0, 0, 0, 0, 0, 1)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
glLoadIdentity()
# [...]
run = True
while run:
# [...]
# init the view matrix
glLoadIdentity()
# apply the movment
if keypress[pygame.K_w]:
glTranslatef(0,0,0.1)
if keypress[pygame.K_s]:
glTranslatef(0,0,-0.1)
if keypress[pygame.K_d]:
glTranslatef(-0.1,0,0)
if keypress[pygame.K_a]:
glTranslatef(0.1,0,0)
# apply the roation
glRotatef(mouseMove[0]*0.1, 0.0, 1.0, 0.0)
# multiply the current matrix by the get the new view matrix and store the final vie matrix
glMultMatrixf(viewMatrix)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
对于向上和向下查找,您必须应用绕 x 轴的最终旋转。旋转的枢轴取决于视角。
必须对角度求和,并且必须在视图矩阵之后应用旋转,否则移动将根据角度改变(“高度”)水平。
viewMatrix = viewTransformMatrix * viewMatrix
finlalMatrix = lookUpDownMatrix * viewMatrix
为此,您必须联合上下旋转矩阵并将其乘以viewMatrix
up_down_angle = 0.0
run = True
while run:
# [...]
# init model view matrix
glLoadIdentity()
# apply the look up and down
up_down_angle += mouseMove[1]*0.1
glRotatef(up_down_angle, 1.0, 0.0, 0.0)
# init the view matrix
glPushMatrix()
glLoadIdentity()
# calculate new `viewMatrix`
# [...]
# apply view matrix
glPopMatrix()
glMultMatrixf(viewMatrix)
See the following example program, which demonstrates the process.
Note, the program keeps the mouse in the center of the window, so you can't "move" the mouse any more.
Therefore the application can be stopped by ESC or return.
The application can be paused by pause or p. When the application is paused, the mouse is not centered to the window.
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
import math
pygame.init()
display = (400, 300)
scree = pygame.display.set_mode(display, DOUBLEBUF | OPENGL)
glEnable(GL_DEPTH_TEST)
glEnable(GL_LIGHTING)
glShadeModel(GL_SMOOTH)
glEnable(GL_COLOR_MATERIAL)
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
glEnable(GL_LIGHT0)
glLightfv(GL_LIGHT0, GL_AMBIENT, [0.5, 0.5, 0.5, 1])
glLightfv(GL_LIGHT0, GL_DIFFUSE, [1.0, 1.0, 1.0, 1])
sphere = gluNewQuadric()
glMatrixMode(GL_PROJECTION)
gluPerspective(45, (display[0]/display[1]), 0.1, 50.0)
glMatrixMode(GL_MODELVIEW)
gluLookAt(0, -8, 0, 0, 0, 0, 0, 0, 1)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
glLoadIdentity()
# init mouse movement and center mouse on screen
displayCenter = [scree.get_size()[i] // 2 for i in range(2)]
mouseMove = [0, 0]
pygame.mouse.set_pos(displayCenter)
up_down_angle = 0.0
paused = False
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE or event.key == pygame.K_RETURN:
run = False
if event.key == pygame.K_PAUSE or event.key == pygame.K_p:
paused = not paused
pygame.mouse.set_pos(displayCenter)
if not paused:
if event.type == pygame.MOUSEMOTION:
mouseMove = [event.pos[i] - displayCenter[i] for i in range(2)]
pygame.mouse.set_pos(displayCenter)
if not paused:
# get keys
keypress = pygame.key.get_pressed()
#mouseMove = pygame.mouse.get_rel()
# init model view matrix
glLoadIdentity()
# apply the look up and down
up_down_angle += mouseMove[1]*0.1
glRotatef(up_down_angle, 1.0, 0.0, 0.0)
# init the view matrix
glPushMatrix()
glLoadIdentity()
# apply the movment
if keypress[pygame.K_w]:
glTranslatef(0,0,0.1)
if keypress[pygame.K_s]:
glTranslatef(0,0,-0.1)
if keypress[pygame.K_d]:
glTranslatef(-0.1,0,0)
if keypress[pygame.K_a]:
glTranslatef(0.1,0,0)
# apply the left and right rotation
glRotatef(mouseMove[0]*0.1, 0.0, 1.0, 0.0)
# multiply the current matrix by the get the new view matrix and store the final vie matrix
glMultMatrixf(viewMatrix)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
# apply view matrix
glPopMatrix()
glMultMatrixf(viewMatrix)
glLightfv(GL_LIGHT0, GL_POSITION, [1, -1, 1, 0])
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
glPushMatrix()
glColor4f(0.5, 0.5, 0.5, 1)
glBegin(GL_QUADS)
glVertex3f(-10, -10, -2)
glVertex3f(10, -10, -2)
glVertex3f(10, 10, -2)
glVertex3f(-10, 10, -2)
glEnd()
glTranslatef(-1.5, 0, 0)
glColor4f(0.5, 0.2, 0.2, 1)
gluSphere(sphere, 1.0, 32, 16)
glTranslatef(3, 0, 0)
glColor4f(0.2, 0.2, 0.5, 1)
gluSphere(sphere, 1.0, 32, 16)
glPopMatrix()
pygame.display.flip()
pygame.time.wait(10)
pygame.quit()