在 GLM 中旋转、缩放和平移 2d 点

Posted

技术标签:

【中文标题】在 GLM 中旋转、缩放和平移 2d 点【英文标题】:Rotating, scaling and translating 2d points in GLM 【发布时间】:2015-12-16 03:30:42 【问题描述】:

我目前正在尝试创建一个 2d 游戏,但我有点震惊,我找不到任何转换,如旋转、缩放、为 vec2 翻译。

例如,据我所知,旋转仅适用于 mat4x4,而 mat4x4 只能乘以 vec4。

有什么理由吗?

我想在 CPU 上计算我的顶点

std::vector<glm::mat2> m;

收集所有矩阵,生成顶点,填充 GPU 缓冲区,然后在一次绘制调用中绘制所有内容。

我将如何在 glm 中执行此操作?只用 mat4 然后忽略 z 和 w 分量?

【问题讨论】:

【参考方案1】:

你应该明白的一点是你不能只忽略 z 组件,更不用说 w 组件了。这取决于您要如何看待问题。问题是您想将 mat2 和 vec2 用于 2D,但是它并不像您想象的那么简单。您正在使用 OpenGL,并且大概它也与着色器一起使用。您至少需要使用glm::mat3,或更好:mat4。这样做的原因是,尽管您希望一切都是 2D 的,但它必须以 3D 的形式完成。 2D 实际上只是 3D,z 缓冲区为 1,剪辑窗格只是静态的,相对于窗口大小。

所以,我的建议是这样的:

    对于您的模型矩阵,您将其作为包含所有数据的glm::mat4,即使您不打算使用它。一致性在这里很重要,尤其是对于转换。

    不要忽略glm::mat4中的z和w分量;它们很重要,因为它们的价值观决定了它们在屏幕上的位置。 OpenGL 需要知道值在 z 平面中的位置。而对于矩阵乘法,需要齐次坐标,所以w分量也很重要。换句话说,您实际上被glm::mat4 卡住了。

    要获得glm::mat4 的转换,您应该

    #include &lt;glm/gtc/matrix_transform.hpp&gt;

单独处理你的精灵;比如有一个Sprite 类,并将它们分组到该类之外。不要递归地进行分组,因为这会导致代码混乱。生成顶点应该在每个 Sprite 的基础上完成;不用担心优化,因为 OpenGL 会为您处理好,更不用说 C++ 方面的编译器了。你很快就会意识到,通过分解这个问题,你可以得到类似的东西

std::vector<Sprite*> sprites;

for (const auto& : i)
    i->init();

// etc...

for (const auto& : i)
    i->render();

关于着色器,您不应该将它们放在 Sprite 类中。拥有一个资源加载器,只需让每个 Sprite 类从该加载器中检索着色器。

最重要的是:记住转换的顺序!

关于精灵的转换,您可以为精灵位置设置glm::vec3,将 z 分量设置为 0。然后您可以通过简单地使用需要 x 和 y 值的函数来移动精灵。使用glm::translate(..) 将这些值输入模型矩阵。关于旋转,您使用glm::rotate() 并简单地使用获取旋转角度的函数。 始终在 Z-PANE 上旋转因此它应该类似于:

modelMatrix = glm::rotate(modelMatrix, glm::radians(angle), glm::vec3(0.f, 0.f, 1.f));

至于缩放,同样是一个合适的setScale() 函数,它接受 x 和 y 的两个值。将 z 分量设置为 1 以防止 Sprite 在 z 中缩放。将值输入glm::scale,如下所示:

modelMatrix = glm::scale(modelMatrix, glm::vec3(scale));

请记住,存储矩阵几乎没有什么好处,因为它们只是数字;它们并没有表明你真正想用它们做什么。 Sprite 类最好封装一个矩阵,以便清楚它们代表什么。

不客气!

【讨论】:

【参考方案2】:

看来我还不够努力http://glm.g-truc.net/0.9.7/api/a00213.html

【讨论】:

以上是关于在 GLM 中旋转、缩放和平移 2d 点的主要内容,如果未能解决你的问题,请参考以下文章

图片处理-opencv-3.图像缩放、旋转、翻转、平移

Stone教程:如何选中平移旋转和缩放实体

使用 OpenGL 固定功能旋转和平移 2D 图像

矩阵的平移旋转与缩放

glm 旋转和平移

在平移/缩放/旋转时,将正弦波推动通过一个几何体