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

4

我目前正在尝试创建一个2D游戏,但我有些惊讶的是,我找不到任何针对vec2的旋转、缩放、平移等变换。

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

这是有什么原因吗?

我希望在CPU上计算我的顶点。

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

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

在glm中应该如何实现这个功能?只需使用mat4,然后忽略z和w分量即可吗?

2个回答

7
你需要明白的一件事是,你不能忽略z分量,更别说w分量了。这取决于你想如何看待问题。问题在于,你想在2D中使用mat2和vec2,但很遗憾并不像你想象的那么简单。你正在使用OpenGL,并且可能还有着shader。你需要至少使用一个glm::mat3,或者更好的是mat4。原因是尽管你想把所有东西都放在2D中,但必须以3D的方式来完成。2D实际上只是具有z缓冲为1和剪辑平面相对于窗口大小静态的3D。
所以,我建议你:
1. 对于模型矩阵,你应该将其作为一个包含所有数据的glm::mat4,即使你不打算使用它。在变换方面,一致性非常重要。 2. 不要忽略glm::mat4中的z和w分量;它们很重要,因为它们的值决定了它们在屏幕上的位置。OpenGL需要知道值在z平面上的位置。对于矩阵乘法,需要使用齐次坐标,因此w分量也很重要。换句话说,你几乎无法摆脱glm::mat4。 3. 要得到glm::mat4的变换,你应该#include 。
将你的精灵分开处理;即使用一个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 类封装一个矩阵,这样就清楚了它们代表什么。

不用谢!


3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接