在GLM中旋转、缩放和平移二维点

Rotating, scaling and translating 2d points in GLM

本文关键字:二维 GLM 旋转 缩放      更新时间:2023-10-16

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

例如,据我所知,rotate只适用于mat4x4,mat4x4只能乘以vec4。

这有什么原因吗?

我想在CPU 上计算我的顶点

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

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

在glm中我该怎么做?只需使用mat4,然后忽略z和w分量?

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

所以,我的建议是:

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

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

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

    #include <glm/gtc/matrix_transform.hpp>

单独对待你的精灵;如中具有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面板上旋转因此它应该类似于以下内容:

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类最好封装一个矩阵,这样就可以清楚地知道它们代表什么。

不客气!

看起来我还不够努力:

CCD_ 15从CCD_。