如何从视图投影矩阵中检索相机 origin/position? (OpenGL)
How to retrieve the camera origin/position from the view projection matrix? (OpenGL)
有没有办法从视图投影矩阵中检索相机 origin/position? (OpenGL)
我正在尝试绘制相机的截锥体,我在计算 Far 和 Near 平面的角时没有问题。
但我不知道如何检索代表相机原点的点。
我期待通过乘以均匀剪辑-space 坐标来检索它:
glm::vec4(0.f, 0.f, 0.f, 1.f)
但我觉得有点像倒置相机位置。 (在截图中标记为X)包括以下所有源代码。
// Homogeneous points for source cube in clip-space.
std::array<glm::vec4, 9> corners =
{
// Far plane
glm::vec4(-1.f,-1.f, 1.f, 1.f), // bottom-left
glm::vec4( 1.f,-1.f, 1.f, 1.f), // bottom-right
glm::vec4( 1.f, 1.f, 1.f, 1.f), // top-right
glm::vec4(-1.f, 1.f, 1.f, 1.f), // top-left
// Near plane
glm::vec4(-1.f,-1.f,-1.f, 1.f), // bottom-left
glm::vec4( 1.f,-1.f,-1.f, 1.f), // bottom-right
glm::vec4( 1.f, 1.f,-1.f, 1.f), // top-right
glm::vec4(-1.f, 1.f,-1.f, 1.f), // top-left
// Camera/screen center position.
// glm::vec4(0.f, 0.f, 0.f, 1.f) // EDIT
glm::vec4(0.f, 0.f,-1.f, 0.f) // SOLVED
};
const auto invMatrix(glm::inverse(viewProjectionMatrix));
for (U32 i = 0; i < corners.size(); i++)
{
corners[i] = invMatrix * corners[i]; // 4x4 * 4x1 matrix/vector multiplication.
corners[i] /= corners[i].w; // Homogeneous to euclidean/cartesian conversion
}
// Far plane.
this->AddLine(corners[0], corners[1], rColor);
this->AddLine(corners[1], corners[2], rColor);
this->AddLine(corners[2], corners[3], rColor);
this->AddLine(corners[3], corners[0], rColor);
// Near plane.
this->AddLine(corners[4], corners[5], rColor);
this->AddLine(corners[5], corners[6], rColor);
this->AddLine(corners[6], corners[7], rColor);
this->AddLine(corners[7], corners[4], rColor);
// Connection from Near rectangle to the Far rectangle.
this->AddLine(corners[0], corners[4], rColor);
this->AddLine(corners[1], corners[5], rColor);
this->AddLine(corners[2], corners[6], rColor);
this->AddLine(corners[3], corners[7], rColor);
// X
this->AddLine(corners[4], corners[8], rColor);
this->AddLine(corners[5], corners[8], rColor);
this->AddLine(corners[6], corners[8], rColor);
this->AddLine(corners[7], corners[8], rColor);
[已解决]
问题是我需要使用 glm::vec4(0.f, 0.f,-1.f, 0.f)
而不是 glm::vec4(0.f, 0.f, 0.f, 1.f)
。
这里是想要的结果:
在一般情况下,如果您只有一个 viewProjection
组合矩阵,则无法从中推断出相机原点。您将需要更多信息。
如果你知道你的投影是正交的(或者实际上是任何一种平行投影),那么相机位置[=31]就没有有意义的概念=] 无论如何,原点只是您选择的一些(或多或少)任意点。要重建它,您需要投影参数将 viewProjection
分解为 view
和 projection
。与完整构建 proj
相比,可能有一些捷径,但这将取决于您可能提前知道/可以假设的实际投影参数的属性。
在透视投影的情况下,情况其实更简单:投影的中心会被投影到某个点无穷大,但我们确切地知道它在齐次剪辑 space 中的位置。对于典型的投影矩阵,它只是 proj * vec4(0,0,0,1)
,也就是 proj
的最后一列。假设默认的 GL 约定,这将类似于 (0, 0, alpha, 0)
。 alpha 的绝对值并不重要,因为这只是一个方向,重要的是符号。同样,假设默认的 GL 约定,alpha 实际上是负的,因此投影中心将在剪辑 space 中转换为 (0,0,-1,0)
。因此,您可以简单地反转计算并从剪辑 space 回到世界 space:p_center = inverse(viewProj) * vec4(0,0,-1,0)
。不要忘记结果仍然是齐次坐标,因此您需要除以结果 w
以获得有意义的 3D 坐标。
有没有办法从视图投影矩阵中检索相机 origin/position? (OpenGL)
我正在尝试绘制相机的截锥体,我在计算 Far 和 Near 平面的角时没有问题。
但我不知道如何检索代表相机原点的点。
我期待通过乘以均匀剪辑-space 坐标来检索它:
glm::vec4(0.f, 0.f, 0.f, 1.f)
但我觉得有点像倒置相机位置。 (在截图中标记为X)包括以下所有源代码。
// Homogeneous points for source cube in clip-space.
std::array<glm::vec4, 9> corners =
{
// Far plane
glm::vec4(-1.f,-1.f, 1.f, 1.f), // bottom-left
glm::vec4( 1.f,-1.f, 1.f, 1.f), // bottom-right
glm::vec4( 1.f, 1.f, 1.f, 1.f), // top-right
glm::vec4(-1.f, 1.f, 1.f, 1.f), // top-left
// Near plane
glm::vec4(-1.f,-1.f,-1.f, 1.f), // bottom-left
glm::vec4( 1.f,-1.f,-1.f, 1.f), // bottom-right
glm::vec4( 1.f, 1.f,-1.f, 1.f), // top-right
glm::vec4(-1.f, 1.f,-1.f, 1.f), // top-left
// Camera/screen center position.
// glm::vec4(0.f, 0.f, 0.f, 1.f) // EDIT
glm::vec4(0.f, 0.f,-1.f, 0.f) // SOLVED
};
const auto invMatrix(glm::inverse(viewProjectionMatrix));
for (U32 i = 0; i < corners.size(); i++)
{
corners[i] = invMatrix * corners[i]; // 4x4 * 4x1 matrix/vector multiplication.
corners[i] /= corners[i].w; // Homogeneous to euclidean/cartesian conversion
}
// Far plane.
this->AddLine(corners[0], corners[1], rColor);
this->AddLine(corners[1], corners[2], rColor);
this->AddLine(corners[2], corners[3], rColor);
this->AddLine(corners[3], corners[0], rColor);
// Near plane.
this->AddLine(corners[4], corners[5], rColor);
this->AddLine(corners[5], corners[6], rColor);
this->AddLine(corners[6], corners[7], rColor);
this->AddLine(corners[7], corners[4], rColor);
// Connection from Near rectangle to the Far rectangle.
this->AddLine(corners[0], corners[4], rColor);
this->AddLine(corners[1], corners[5], rColor);
this->AddLine(corners[2], corners[6], rColor);
this->AddLine(corners[3], corners[7], rColor);
// X
this->AddLine(corners[4], corners[8], rColor);
this->AddLine(corners[5], corners[8], rColor);
this->AddLine(corners[6], corners[8], rColor);
this->AddLine(corners[7], corners[8], rColor);
[已解决]
问题是我需要使用 glm::vec4(0.f, 0.f,-1.f, 0.f)
而不是 glm::vec4(0.f, 0.f, 0.f, 1.f)
。
这里是想要的结果:
在一般情况下,如果您只有一个 viewProjection
组合矩阵,则无法从中推断出相机原点。您将需要更多信息。
如果你知道你的投影是正交的(或者实际上是任何一种平行投影),那么相机位置[=31]就没有有意义的概念=] 无论如何,原点只是您选择的一些(或多或少)任意点。要重建它,您需要投影参数将 viewProjection
分解为 view
和 projection
。与完整构建 proj
相比,可能有一些捷径,但这将取决于您可能提前知道/可以假设的实际投影参数的属性。
在透视投影的情况下,情况其实更简单:投影的中心会被投影到某个点无穷大,但我们确切地知道它在齐次剪辑 space 中的位置。对于典型的投影矩阵,它只是 proj * vec4(0,0,0,1)
,也就是 proj
的最后一列。假设默认的 GL 约定,这将类似于 (0, 0, alpha, 0)
。 alpha 的绝对值并不重要,因为这只是一个方向,重要的是符号。同样,假设默认的 GL 约定,alpha 实际上是负的,因此投影中心将在剪辑 space 中转换为 (0,0,-1,0)
。因此,您可以简单地反转计算并从剪辑 space 回到世界 space:p_center = inverse(viewProj) * vec4(0,0,-1,0)
。不要忘记结果仍然是齐次坐标,因此您需要除以结果 w
以获得有意义的 3D 坐标。