如何使用glm :: project来获取世界空间中某个点的坐标?

Chi*_*hin 2 opengl graphics glm-math

我在2D空间中有一个点(1,2),我表示为向量:

glm::vec3 pt = glm::vec3(1, 2, 0)
Run Code Online (Sandbox Code Playgroud)

(这里我将第三个组件设置为0 - 不确定这是否正确?)

我有一个模型视图矩阵来应用翻译到这一点:

glm::mat4 ModelView = glm::mat4(1.0f);
ModelView = glm::translate(ModelView, glm::vec3(3.0f, 3.0f, 0.0f));
Run Code Online (Sandbox Code Playgroud)

现在我想找到世界空间中点的实际坐标.我做了一些研究,glm::project()似乎是我可以用来做这件事的.它包含4个参数:

detail::tvec3<T> glm::gtc::matrix_transform::project(detail::tvec3<T> const & obj,
                                                     detail::tmat4x4<T> const & model,
                                                     detail::tmat4x4<T> const & proj,
                                                     detail::tvec4<U> const & viewport 
)
Run Code Online (Sandbox Code Playgroud)

前两个参数是我已经拥有的点和模型视图矩阵.但是我应该将什么用于第3和第4个参数(投影矩阵和视口矢量)?我该如何创建/获取它们?

dam*_*911 8

我想你可能会更感兴趣的GLM :: unProject,逆GLM ::项目.长话短说,glm :: frustum,glm :: perspectiveglm :: perspectiveFov是构建proj矩阵的好选择,而某些东西vec4(0, 0, screenWidth, screenHeight)应该是有效的视口向量.这实际上取决于您如何设置OpenGL相机.

一个完整的例子应该有帮助

屏幕空间和背面

导入所需的库:

#include <iostream>
#include <glm/vec3.hpp>
#include <glm/mat4x4.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/matrix_transform.hpp>

using namespace std;
using namespace glm;
Run Code Online (Sandbox Code Playgroud)

我们的主要:

int main(int argc, char *argv[])
{
Run Code Online (Sandbox Code Playgroud)

这是所谓的对象空间中的原始点.如果从文件加载网格,则会在文件中找到这些XYZ坐标.

    vec3 original(1.0f, -2.0f, 3.0f);
Run Code Online (Sandbox Code Playgroud)

所述模型矩阵指定了对象被定位在场景中.的视图矩阵指定定位对象相对于相机的相对位置.在OpenGL中,这些矩阵通常组合在一个名为modelview的矩阵中.我选择了这里的术语模型,因为这是GLM文档使用的,但是你的术语模型视图更适合这种情况,我相信:

    mat4 model = translate(mat4(1.0f), vec3(0.0f, 0.0f, -10.0f));
Run Code Online (Sandbox Code Playgroud)

所述投影矩阵表示镜头和照相机的光圈,并且是实际变形的,因为它模拟的角度来看,使过远更小的物体的方式现场.您可以使用GLM函数,例如视锥体,其行为类似于GL对应的glFrustum:

    mat4 projection = frustum(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 100.0f);
Run Code Online (Sandbox Code Playgroud)

视口指定绘图区域的大小和位置.对于640x360窗口,您通常会使用以下内容:

    vec4 viewport(0.0f, 0.0f, 640.0f, 360.0f);
Run Code Online (Sandbox Code Playgroud)

项目的功能做投影原点到屏幕的法宝:

    vec3 projected = glm::project(original, model, projection, viewport);
Run Code Online (Sandbox Code Playgroud)

所述unProject功能则正好相反:

    vec3 unprojected = glm::unProject(projected, model, projection, viewport);
Run Code Online (Sandbox Code Playgroud)

您现在可以看到这两个函数是另一个函数的反函数:

    cout << original.x << " " << original.y << " " << original.z << endl;
    cout << projected.x << " " << projected.y << " " << projected.z << endl;
    cout << unprojected.x << " " << unprojected.y << " " << unprojected.z << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在数学上,这是发生了什么幕后:一个点原来物体空间投射到屏幕空间由四个矩阵模型,视图,投影和视口矩阵相乘:

projected = Viewport * Projection * View * Model * original
Run Code Online (Sandbox Code Playgroud)

虽然您正在寻找的相反转型基本上是:

unprojected = (Viewport * Projection * View * Model)^-1 * projected
Run Code Online (Sandbox Code Playgroud)

完整代码

#include <iostream>
#include <glm/vec3.hpp>
#include <glm/mat4x4.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/matrix_transform.hpp>

using namespace std;
using namespace glm;

int main(int argc, char *argv[])
{
    vec3 original(1.0f, -2.0f, 3.0f);

    mat4 model = translate(mat4(1.0f), vec3(0.0f, 0.0f, -10.0f));
    mat4 projection = frustum(-1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 100.0f);
    vec4 viewport(0.0f, 0.0f, 640.0f, 360.0f);

    vec3 projected = glm::project(original, model, projection, viewport);
    vec3 unprojected = glm::unProject(projected, model, projection, viewport);

    cout << original.x << " " << original.y << " " << original.z << endl;
    cout << projected.x << " " << projected.y << " " << projected.z << endl;
    cout << unprojected.x << " " << unprojected.y << " " << unprojected.z << endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)