任何人都可以帮助我从投影矩阵 44 中获取左、右、下、上、近和远边界值吗?
3 回答
以下是Christian Rau提到 的方程系统的分辨率:
对于正交矩阵 :
near = (1+m34)/m33;
far = -(1-m34)/m33;
bottom = (1-m24)/m22;
top = -(1+m24)/m22;
left = -(1+m14)/m11;
right = (1-m14)/m11;
对于透视矩阵:
near = m34/(m33-1);
far = m34/(m33+1);
bottom = near * (m23-1)/m22;
top = near * (m23+1)/m22;
left = near * (m13-1)/m11;
right = near * (m13+1)/m11;
您可以用glOrtho和glFrustum文档中定义的公式替换值 m11、m12 等,以检查它是否正确。
首先,您可以查看这些矩阵是如何为对glOrtho
和glFrustum
(或框架中的类似函数)的相应调用定义的。接下来的步骤取决于投影的类型,可以是正投影(例如从glOrtho
)还是透视(例如从glFrustum
或gluPerspective
),这可以通过查看第 3 列来决定。
现在对于正交矩阵,很容易得到两个方程:
right - left = 2 / m11
right + left = -2 * m14 / m11
从这些你可以很容易地计算right = (1-m14) / m11
和left = right - 2/m11
(你可以重新检查我在心算过程中犯的任何错误)。其他两对参数也类似(注意 的符号m33
)。
对于透视投影,您应该首先计算near
和far
使用m33
and m34
。然后您可以计算right/left
并bottom/top
类似于上述情况,但使用计算near
值。
所以总而言之,一旦你知道了基于参数的矩阵公式,它真的可以归结为一堆易于求解的简单 2x2 方程组。一个更有趣的问题是,为什么您实际上需要从投影矩阵计算这些参数。如果你真的需要它们,你应该只存储它们(因为你是构造矩阵的人,无论如何)。否则,这听起来像是将 OpenGL 用于更多事情(如场景管理)的另一个实例,而不是它的实际用途,它只是一个简单的绘图 API。
为了将来参考,我在下面复制了 C++ 中的近、远等值,用于具有 0 索引列主要投影矩阵的 OpenGL:
float near = m_projectionMatrix[3][2] / (m_projectionMatrix[2][2] - 1.0f);
float far = m_projectionMatrix[3][2] / (m_projectionMatrix[2][2] + 1.0f);
logStderr(VERBOSE, "near, far %5.2f, %5.2f...\n", near, far);
float nearBottom = near * (m_projectionMatrix[2][1] - 1) / m_projectionMatrix[1][1];
float nearTop = near * (m_projectionMatrix[2][1] + 1) / m_projectionMatrix[1][1];
float nearLeft = near * (m_projectionMatrix[2][0] - 1) / m_projectionMatrix[0][0];
float nearRight = near * (m_projectionMatrix[2][0] + 1) / m_projectionMatrix[0][0];
logStderr(VERBOSE, "nearLeft, nearRight, nearTop, nearBottom %5.2f, %5.2f, %5.2f, %5.2f...\n", nearLeft, nearRight, nearTop, nearBottom);
float farBottom = far * (m_projectionMatrix[2][1] - 1) / m_projectionMatrix[1][1];
float farTop = far * (m_projectionMatrix[2][1] + 1) / m_projectionMatrix[1][1];
float farLeft = far * (m_projectionMatrix[2][0] - 1) / m_projectionMatrix[0][0];
float farRight = far * (m_projectionMatrix[2][0] + 1) / m_projectionMatrix[0][0];
logStderr(VERBOSE, "farLeft, farRight, farTop, farBottom %5.2f, %5.2f, %5.2f, %5.2f...\n", farLeft, farRight, farTop, farBottom);