4

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

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]

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

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

4

2 回答 2

1

如果您想要使用 OpenGL 在 XY 平面中渲染的 2D 图像,则(1)围绕点P逆时针旋转 ( 2)按S缩放,然后(3)平移以使C处的像素(在新缩放和旋转的图像)位于原点,您将使用此转换:

  1. 通过-P平移(这会将P处的像素移动到原点)
  2. 旋转一个
  3. P翻译(这会将原点移回原来的位置)
  4. 按S缩放 (如果你之前这样做,你的旋转会搞砸)
  5. -C翻译

如果我们在原点渲染 2D 图像,您还需要沿负 z 轴平移一些值才能看到它。

通常,您只需使用 OpenGL 基础知识(glTranslatefglScalefglRotatef等)即可。你会按照我列出的相反顺序来做。既然你想使用glLoadMatrix,你会按照我用 Eigen 描述的顺序做事。重要的是要记住 OpenGL 需要一个 Column Major 矩阵(但这似乎是 Eigen 的默认值;所以这可能不是问题)。

于 2012-05-18T18:21:25.897 回答
0

JCooper 很好地解释了构建初始矩阵的步骤。

但是我最终以不同的方式解决了这个问题。当时几乎没有什么对我来说不明显的其他事情和步骤。请参阅 JCooper 答案的评论。首先是实现所有矩阵运算都是相对的。

因此,如果要使用绝对 xy 轴定位或移动相机,则必须首先分解矩阵以提取其轴不变的绝对位置。然后你通过新旧位置的差异来翻译矩阵。

这是使用 Eigen 执行此操作的方法:

首先计算 Affine2f 矩阵cmat标量行列式 D。使用 Eigen 可以使用D = cmat.linear().determinant();. matrev接下来使用 D 计算当前旋转+缩放矩阵 R 的“反向”矩阵。matrev = (RS.array() / (1.0f / determ)).matrix());其中 RS 是cmat.matrix().topLeftCorner(2,2) 相机的绝对位置 P 然后由P = invmat * -C其中 C给出cmat.matrix().col(2).head<2>()

现在我们可以沿绝对轴重新定位相机并保持旋转+缩放相同:V = RS * (T - P) 其中 RS 与以前相同,T 是新位置 vec,P 是分解后的位置 vec。然后cmat简单地通过 V 平移来移动相机:cmat.pretranslate(V)

于 2016-11-19T18:58:16.470 回答