Вы можете использовать glRotate
для вращения вокруг оси на величину, которая определяется относительным движением мыши (pygame.mouse.get_rel()
):
mouseMove = pygame.mouse.get_rel()
glRotatef(mouseMove[0]*0.1, 0.0, 1.0, 0.0)
Но это вас не удовлетворит, поскольку решение больше не работает, если мышь покидает окно.
Вы должны отцентрировать мышь по центру экрана с помощью pygame.mouse.set_pos()
в каждом кадре.Получить движение мышки по событию pygame.MOUSEMOTION
.Например:
# 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
и glTranslate
устанавливают матрицу и умножают текущую матрицу на новую матрицу.
currentMatrix = currentMatrix * newMatrix
Идеально подходит для анимации и трансформации моделей, но это неправильный способ для движения от первого лица, когда необходимо изменить положение и точку камеры.
viewMatrix = viewTransformMatrix * viewMatrix
Комувыполняйте такие операции glGetFloatv(GL_MODELVIEW_MATRIX)
и glMultMatrixf
.
Инициализируйте матрицу вида с помощью gluLookAt
и загрузите матрицу вида в переменную (viewMatrix
) на glGetFloatv(GL_MODELVIEW_MATRIX)
, до основного цикла.
В главном цикле для каждого кадра:
- загрузить Идентификационную матрицу (
glLoadIdentity
) - выполнить новые преобразования для вида (
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
Для этого выНам нужно объединить матрицу вращения вверх и вниз и умножить ее на vieMatrix
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)
См. следующий пример программы, которая демонстрирует процесс.
Обратите внимание, программа держит мышьв центре окна, так что вы больше не можете «двигать» мышью.Поэтому приложение может быть остановлено с помощью ESC или return .
Приложение может быть приостановлено с помощью pause или р .Если приложение приостановлено, мышь не центрируется относительно окна.
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()