Math 用特征值法计算二维摄像机模型视图矩阵
我试图计算我的2D相机的模型视图矩阵,但我不能得到正确的公式。我使用Affine3f变换类,因此矩阵与OpenGL兼容。这是我通过反复试验得到的最接近的结果。这段代码可以旋转和缩放摄影机,但如果同时应用平移和旋转,摄影机的移动就会混乱:摄影机以旋转方式移动,这不是我想要的。(这可能是因为我先应用旋转矩阵,然后应用平移) 我想要的是,相机将围绕屏幕空间的偏移位置旋转和缩放{(0,0)在本例中是屏幕的中间},然后沿着世界空间中的全局xy轴定位{(0,0)最初也是在屏幕的中间}到最终位置。我该怎么做Math 用特征值法计算二维摄像机模型视图矩阵,math,opengl,matrix,camera,eigen,Math,Opengl,Matrix,Camera,Eigen,我试图计算我的2D相机的模型视图矩阵,但我不能得到正确的公式。我使用Affine3f变换类,因此矩阵与OpenGL兼容。这是我通过反复试验得到的最接近的结果。这段代码可以旋转和缩放摄影机,但如果同时应用平移和旋转,摄影机的移动就会混乱:摄影机以旋转方式移动,这不是我想要的。(这可能是因为我先应用旋转矩阵,然后应用平移) 我想要的是,相机将围绕屏幕空间的偏移位置旋转和缩放{(0,0)在本例中是屏幕的中间},然后沿着世界空间中的全局xy轴定位{(0,0)最初也是在屏幕的中间}到最终位置。我该怎么做
请注意,我还设置了一个正交投影矩阵,这可能会影响此问题。如果您希望使用OpenGL在XY平面中渲染二维图像,请(1)围绕点p逆时针旋转a,(2)缩放S,然后(3)平移以使C(在新缩放和旋转的图像中)位于原点时,可以使用以下变换:
通常,您只需使用OpenGL基础知识(
glTranslatef
,glScalef
,glRotatef
,等等)就可以做到这一点。你可以按照我列出的相反顺序来做。既然你想使用glLoadMatrix
,你就应该按照我用Egeng描述的顺序来做。记住OpenGL需要一个列主矩阵(但这似乎是Egeng的默认值;所以这可能不是问题).JCooper非常好地解释了构建初始矩阵的步骤
然而,我最终以不同的方式解决了这个问题。在当时,我没有明显的其他事情和步骤。请参阅JCooper answer的评论。首先,要实现所有矩阵运算都是相对的
因此,如果要使用绝对xy轴定位或移动相机,必须首先分解矩阵以提取其绝对位置(轴不变),然后根据新旧位置的差异平移矩阵
以下是使用Eigen进行此操作的方法:
首先计算仿射2f矩阵cmat
标量行列式D。使用特征值,这是通过D=cmat.linear().determinate();
完成的。接下来使用D计算当前旋转+缩放矩阵R的“反向”矩阵matrev
。matrev=(RS.array()/(1.0f/determ)).matrix()代码>其中RS是cmat.matrix().topLeftCorner(2,2)
然后,绝对摄像机位置P由P=invmat*-C
给出,其中C是cmat.matrix().col(2.head()
现在我们可以沿绝对轴将相机重新定位到任何位置,并保持旋转+缩放不变:V=RS*(T-p),其中RS与之前相同,T是新的位置向量,p是分解的位置向量。
cmat
然后简单地用V翻译来移动相机:cmat.pretranslate(V)
谢谢,现在看起来效果更好了。然而,相机并没有以我预想的方式移动:增加x坐标也会影响y坐标,因此相机沿着旋转的xy轴而不是未旋转的xy轴移动。这是我的问题的第二部分,让相机按我想要的方式移动。我希望摄影机仅围绕点旋转和缩放,然后以应用的旋转不影响此平移的方式将摄影机移动到其位置。PS:我将尽可能避免使用固定管道的东西,因此更改为GL 3.0+着色器和更新的着色器将是无痛的。@JATothrim我浏览了Eigen规范。它说您使用的转换应用于矩阵的右侧。我希望他们在左边申请。因为它们是在右边应用的,所以您需要按相反的顺序应用它们。或者,你可以使用“预旋转”和“预平移”。它很近,但不是很近。摄影机现在围绕该点旋转和缩放,如果不旋转,则可以进行平移。旋转打乱了平移(反之亦然),相机不会像我例外那样移动。旋转90度,y轴在相机移动中变成x轴!我该如何预防呢?我想我终于解决了这个移动问题。错误在于我重置了modelview以识别每一帧,即使将相机相对于其当前位置移动时也是如此。正因为如此,从modelview中提取X向量,然后在该方向上进行转换是行不通的!我现在觉得自己很愚蠢。课程:无休止地链接变换,而不必返回到单位矩阵,这是可以的。
Eigen::Affine3f modelview;
modelview.setIdentity();
modelview.translate(Eigen::Vector3f(camera_offset_x, camera_offset_y, 0.0f));
modelview.scale(Eigen::Vector3f(camera_zoom_x, camera_zoom_y, 0.0f));
modelview.rotate(Eigen::AngleAxisf(camera_angle, Eigen::Vector3f::UnitZ()));
modelview.translate(Eigen::Vector3f(camera_x, camera_y, 0.0f));
[loadmatrix_to_gl]