Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Math 用特征值法计算二维摄像机模型视图矩阵_Math_Opengl_Matrix_Camera_Eigen - Fatal编程技术网

Math 用特征值法计算二维摄像机模型视图矩阵

Math 用特征值法计算二维摄像机模型视图矩阵,math,opengl,matrix,camera,eigen,Math,Opengl,Matrix,Camera,Eigen,我试图计算我的2D相机的模型视图矩阵,但我不能得到正确的公式。我使用Affine3f变换类,因此矩阵与OpenGL兼容。这是我通过反复试验得到的最接近的结果。这段代码可以旋转和缩放摄影机,但如果同时应用平移和旋转,摄影机的移动就会混乱:摄影机以旋转方式移动,这不是我想要的。(这可能是因为我先应用旋转矩阵,然后应用平移) 我想要的是,相机将围绕屏幕空间的偏移位置旋转和缩放{(0,0)在本例中是屏幕的中间},然后沿着世界空间中的全局xy轴定位{(0,0)最初也是在屏幕的中间}到最终位置。我该怎么做

我试图计算我的2D相机的模型视图矩阵,但我不能得到正确的公式。我使用Affine3f变换类,因此矩阵与OpenGL兼容。这是我通过反复试验得到的最接近的结果。这段代码可以旋转和缩放摄影机,但如果同时应用平移和旋转,摄影机的移动就会混乱:摄影机以旋转方式移动,这不是我想要的。(这可能是因为我先应用旋转矩阵,然后应用平移)

我想要的是,相机将围绕屏幕空间的偏移位置旋转和缩放{(0,0)在本例中是屏幕的中间},然后沿着世界空间中的全局xy轴定位{(0,0)最初也是在屏幕的中间}到最终位置。我该怎么做


请注意,我还设置了一个正交投影矩阵,这可能会影响此问题。

如果您希望使用OpenGL在XY平面中渲染二维图像,请(1)围绕点p逆时针旋转a,(2)缩放S,然后(3)平移以使C(在新缩放和旋转的图像中)位于原点时,可以使用以下变换:

  • -P平移(这会将P处的像素移动到原点)
  • 旋转a
  • 通过P进行翻译(这会将原点移回原来的位置)
  • S缩放(如果你早一点这样做,你的旋转就会混乱)
  • 通过-C进行翻译
  • 如果我们在原点渲染的2D图像,您还需要沿负z轴平移一些值才能看到它


    通常,您只需使用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]