【问题标题】:Rotating, scaling and translating 2d points in GLM在 GLM 中旋转、缩放和平移 2d 点
【发布时间】:2024-08-04 07:15:02
【问题描述】:

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

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

有什么理由吗?

我想在 CPU 上计算我的顶点

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

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

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

【问题讨论】:

    标签: c++ opengl glm-math


    【解决方案1】:

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

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

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

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

    3. 要获得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】:

      【讨论】:

        最近更新 更多