解释 OpenGL 如何管理它的变换矩阵
Posted
技术标签:
【中文标题】解释 OpenGL 如何管理它的变换矩阵【英文标题】:Explanation of how OpenGL manages its transformation matrices 【发布时间】:2020-04-28 14:40:34 【问题描述】:我在 Python 中使用 PyOpenGL 模块进行编程。我开始研究用于视野操作的相机模块,但我坚持使用 gluLookAt() 函数。我的问题是,当我按下一个键来平移相机时,它可以正常工作,但是当我释放键时它不会停止。我认为这可能是因为我必须重新初始化转换矩阵或其他东西。我已经看到我应该推送和弹出矩阵,或者在某处加载单位矩阵,但现在我对 OpenGL 对我假设 gluLookAt() 给出的矩阵究竟做了什么感到非常困惑。
这是我的代码:
import pygame
from pygame.locals import *
import numpy as np
import glm
from math import *
from OpenGL.GLU import *
from OpenGL.GL import *
class camera:
def __init__(self, position, angles, target):
self.position = glm.vec3(position[0], position[1], position[2])
self.front = glm.normalize(self.position - glm.vec3(target[0], target[1], target[2]))
self.upVector = glm.normalize(glm.cross(self.front, glm.normalize(glm.cross(self.front, glm.vec3(0, 1, 0)))))
def update(self):
glMatrixMode(GL_MODELVIEW)
gluLookAt(self.position[0], self.position[1], self.position[2], self.position[0] + self.front[0],
self.position[1] + self.front[1], self.position[2] + self.front[2], self.upVector[0], self.upVector[1], self.upVector[2])
def getPos(self):
return self.position
def translateCamera(self, vector):
self.position = self.position + vector
def keyboardControl(self):
keys = pygame.key.get_pressed()
if keys[K_LALT] and keys[K_F4]:
pygame.quit()
quit()
if keys[K_w] and not isSprinting:
self.position += self.front * 0.02085
if keys[K_s]:
self.position -= self.front * 0.02085
if keys[K_d]:
self.position += glm.normalize(glm.cross(self.front, self.upVector)) * 0.02085
if keys[K_a]:
self.position -= glm.normalize(glm.cross(self.front, self.upVector)) * 0.02085
当我松开按键时,相机一直在滑行,我想可能是因为我没有在某处重置矩阵,它只是一遍又一遍地应用 gluLookAt() 给出的矩阵。
我还尝试了 GLM,并设法使用 glm.lookAt() 创建了我想要的转换矩阵,但我不知道如何传递它,所以 OpenGL 处理它。
我应该如何使用 glPushMatrix 和 glPopMatrix?我什么时候必须使用 glLoadIdentity?
【问题讨论】:
从您报告的错误来看,更有可能是您没有正确处理关键事件。连续运动是由您使用的矩阵和向量的连续变化引起的。每次按下和释放按钮时都会打印“按下键”和“释放键”之类的内容。然后回来报告。 【参考方案1】:当我松开按键时相机一直在滑行,我想可能是因为我没有在某处重置矩阵,它只是一遍又一遍地应用
gluLookAt()
给出的矩阵。
gluLookAt
不只是设置一个矩阵,如果定义一个矩阵并将当前矩阵乘以新矩阵。
注意所有矩阵运算,如glRotate
、glScale
、glTranslate
等。将矩阵乘以当前矩阵。
在gluLookAt
之前加载Identity matrix,glLoadIdentity
:
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
gluLookAt(
self.position[0], self.position[1], self.position[2],
self.position[0] + self.front[0], self.position[1] + self.front[1], self.position[2] + self.front[2],
self.upVector[0], self.upVector[1], self.upVector[2])
我还尝试了 GLM,并设法使用 glm.lookAt()
创建了我想要的转换矩阵,但我不知道如何传递它,所以 OpenGL 处理它。
使用glLoadMatrix
和glm.value_ptr
加载矩阵:
viewMatrix = glm.lookAt(self.position, self.position + self.front, self.upVector)
vieMatList = [viewMatrix[i][j] for i in range(4) for j in range(4)]
glMatrixMode(GL_MODELVIEW)
glLoadMatrixf(vieMatList)
注意一个矩阵可以乘以glMultMatrix
。
【讨论】:
我尝试了这两个建议。使用 gluLookAt 的那个有点工作,问题是场景现在是二维的(我正在使用立方体进行调试,它只渲染某些 z 值之间的一个面),但我认为这是另一个问题和与此问题无关。对于使用 GLM 的人,它返回一个 AttributeError。另外,我应该使用 glLoadMatrixf() 还是 glLoadMatrixd()? 场景不是二维的,它似乎是二维的。这与观点和projection有关。无论如何,解释所有这些都是为了广泛的答案。有很多不错的教程,推荐阅读LearnOpenGL - Camera/View space。是的,我知道本教程的语言是 C++。 OpenGL with PyOpenGL introduction 似乎也是一个不错的教程。以上是关于解释 OpenGL 如何管理它的变换矩阵的主要内容,如果未能解决你的问题,请参考以下文章