在 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 <glm/gtc/matrix_transform.hpp>
单独处理你的精灵;比如有一个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 点的主要内容,如果未能解决你的问题,请参考以下文章