如何在 PyOpenGL 中获取当前相机位置?
How to get current camera position in PyOpenGL?
我正在用 OpenGL 制作一个游戏,其中有些物体朝向您。为此,我必须获取当前的相机位置。我知道在 OpenGL 中相机总是停留在 (0,0,0) 位置,但我想根据世界获取相机的当前位置。我该怎么做>
我试过 viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
camera_pos = viewMatrix[3]
,但我的相机有俯仰和偏航功能,而且当我这样做时位置总是会改变。我该如何解决这个问题?
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import math,random
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:
run = False
if event.key == pygame.K_p:
paused = not paused
if not paused:
if event.type == pygame.MOUSEMOTION:
mouseMove = [event.pos[i] - displayCenter[i] for i in range(2)]
pygame.mouse.set_pos(displayCenter)
pygame.mouse.set_visible(False)
if not paused:
#Get keys
keypress = pygame.key.get_pressed()
#Init model view matrix
glLoadIdentity()
#------------------------View------------------------
#Apply the look up and down (with 90° angle limit)
if up_down_angle < -90:
if mouseMove[1] > 0:
up_down_angle += mouseMove[1]*0.1
elif up_down_angle > 90:
if mouseMove[1] < 0:
up_down_angle += mouseMove[1]*0.1
else:
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 movement
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 look left and right
glRotatef(mouseMove[0]*0.1, 0.0, 1.0, 0.0)
#------------------------View------------------------
#------------------------Draw------------------------
#Multiply the current matrix by the new view matrix and store the final view matrix
glMultMatrixf(viewMatrix)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
camera_pos = viewMatrix[3] #Incorrect
print(camera_pos) #print the output
#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.2, 0.2, 0.5, 1)
for person in persons:
person.draw()
ground.draw()
glutSwapBuffers()
glPopMatrix()
#------------------------Draw------------------------
pygame.display.flip()
pygame.time.wait(10)
pygame.quit()
我预计当我进行视图旋转时我的坐标不会移动,但是 camera_pos 的输出会在这样做时发生变化。
视图矩阵将世界 space 转换为视图 space。这意味着视图矩阵不是包含相机位置的矩阵。视图矩阵是包含相机位置和方向的 inverse matrix。
编写一个可以计算 4x4 矩阵的逆矩阵的函数:
def InverseMat44(mat):
m = [mat[i][j] for i in range(4) for j in range(4)]
inv = [0]*16
inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10]
inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10]
inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9]
inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9]
inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10]
inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10]
inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9]
inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9]
inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6]
inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6]
inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5]
inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5]
inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6]
inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6]
inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5]
inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5]
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12]
for i in range(16):
inv[i] /= det;
return inv;
另见 inverting a 4x4 matrix and Find the inverse of a 4×4 matrix。
并计算视图矩阵的逆矩阵:
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
invVM = InverseMat44(viewMatrix)
camera_pos = (invVM[12], invVM[13], invVM[14])
print(camera_pos)
逆矩阵也可以通过库来计算。例如numpy.linalg.inv
from NumPy library or glm.inverse
from PyGLM图书馆。
我正在用 OpenGL 制作一个游戏,其中有些物体朝向您。为此,我必须获取当前的相机位置。我知道在 OpenGL 中相机总是停留在 (0,0,0) 位置,但我想根据世界获取相机的当前位置。我该怎么做>
我试过 viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
camera_pos = viewMatrix[3]
,但我的相机有俯仰和偏航功能,而且当我这样做时位置总是会改变。我该如何解决这个问题?
import pygame
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import math,random
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:
run = False
if event.key == pygame.K_p:
paused = not paused
if not paused:
if event.type == pygame.MOUSEMOTION:
mouseMove = [event.pos[i] - displayCenter[i] for i in range(2)]
pygame.mouse.set_pos(displayCenter)
pygame.mouse.set_visible(False)
if not paused:
#Get keys
keypress = pygame.key.get_pressed()
#Init model view matrix
glLoadIdentity()
#------------------------View------------------------
#Apply the look up and down (with 90° angle limit)
if up_down_angle < -90:
if mouseMove[1] > 0:
up_down_angle += mouseMove[1]*0.1
elif up_down_angle > 90:
if mouseMove[1] < 0:
up_down_angle += mouseMove[1]*0.1
else:
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 movement
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 look left and right
glRotatef(mouseMove[0]*0.1, 0.0, 1.0, 0.0)
#------------------------View------------------------
#------------------------Draw------------------------
#Multiply the current matrix by the new view matrix and store the final view matrix
glMultMatrixf(viewMatrix)
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
camera_pos = viewMatrix[3] #Incorrect
print(camera_pos) #print the output
#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.2, 0.2, 0.5, 1)
for person in persons:
person.draw()
ground.draw()
glutSwapBuffers()
glPopMatrix()
#------------------------Draw------------------------
pygame.display.flip()
pygame.time.wait(10)
pygame.quit()
我预计当我进行视图旋转时我的坐标不会移动,但是 camera_pos 的输出会在这样做时发生变化。
视图矩阵将世界 space 转换为视图 space。这意味着视图矩阵不是包含相机位置的矩阵。视图矩阵是包含相机位置和方向的 inverse matrix。
编写一个可以计算 4x4 矩阵的逆矩阵的函数:
def InverseMat44(mat):
m = [mat[i][j] for i in range(4) for j in range(4)]
inv = [0]*16
inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10]
inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10]
inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9]
inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9]
inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10]
inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10]
inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9]
inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9]
inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6]
inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6]
inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5]
inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5]
inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6]
inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6]
inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5]
inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5]
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12]
for i in range(16):
inv[i] /= det;
return inv;
另见 inverting a 4x4 matrix and Find the inverse of a 4×4 matrix。
并计算视图矩阵的逆矩阵:
viewMatrix = glGetFloatv(GL_MODELVIEW_MATRIX)
invVM = InverseMat44(viewMatrix)
camera_pos = (invVM[12], invVM[13], invVM[14])
print(camera_pos)
逆矩阵也可以通过库来计算。例如numpy.linalg.inv
from NumPy library or glm.inverse
from PyGLM图书馆。