GLM 不断提供不稳定的转换和旋转

Posted

技术标签:

【中文标题】GLM 不断提供不稳定的转换和旋转【英文标题】:GLM Keeps Providing Choppy Transformation and Rotations 【发布时间】:2013-11-13 23:22:56 【问题描述】:

我目前遇到的问题是 GLM 提供不稳定的变换和旋转。我的意思是他们并不顺利。我正在使用 GLFW 3、GLM 和 OpenGL 3.2。我正在尝试使用操纵杆输入来转换一个简单的四边形。起初,我认为问题是由操纵杆引起的。为了反驳这一点,我更改了代码以独立于用户输入旋转四边形,但依赖于 deltaTime。下面是一些代码段。我假设它与我如何旋转矩阵有关?

CPP 文件:

float speed = 3.0f;
float deadZone = 0.10f;
glm::vec2 direction(0.0f);

while (!glfwWindowShouldClose(window))

    currentTime = glfwGetTime();
    deltaTime = (currentTime - lastUpdate) * 1000.0f;

    //Update logic
    inputHandler->tick(deltaTime);

    float inputX, inputY;
    inputX = inputHandler->getGamepad(0)->getAxes(AXIS::HORIZONTAL);
    inputY = inputHandler->getGamepad(0)->getAxes(AXIS::VERTICAL);

    float magnitude = sqrtf((inputX * inputX) + (inputY * inputY));
    if (magnitude > deadZone) //Radial dead zone detection
    
        //Could the stutter be caused by type casting?
        direction.x += inputX * float((speed * deltaTime) / 1000.0f);
        direction.y += inputY * float((speed * deltaTime) / 1000.0f);
    

    ... //Set vertex values and UV coord

    //Set the matrix values according to the joystick input
    glm::mat4 MVP(1.0f);
    MVP = glm::translate(MVP, glm::vec3(direction, 0.0f));
    glUniformMatrix4fv(mvpID, 1, GL_FALSE, glm::value_ptr(MVP));

    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    ...

顶点着色器:

#version 150

in vec2 vertexPosition_modelspace;
in vec2 UV;

uniform mat4 MVP;

out vec2 vUV;

void main() 
    vUV = UV;
    gl_Position = MVP * vec4(vertexPosition_modelspace, 0, 1);

【问题讨论】:

“波涛汹涌”是什么意思?你只是有一个缓慢的帧速率? GLM 不是问题。 不,这不是帧率问题。我查了一下,我一直在 350FPS 以上。我想可能是我的帧率太高了,所以我启用了 VSync。可悲的是,这没有任何帮助。下面是我所说的不连贯的一个例子:对象将以每刻 4px 的平滑移动,然后突然,在单个刻,对象将移动约 32px。再次,我在发生这种跳跃时检查了我的帧率,它从未低于 350(垂直同步时为 59)。 您是否尝试过打印每个刻度的增量? @GraphicsMuncher 我刚刚在启用 VSync 的情况下进行了尝试。恒定输出会降低窗口的响应能力,但 deltaTime 的范围似乎在 0.2 - 0.5 之间。由于输出量巨大,很难注意到任何异常情况。 你在运行 linux 吗?我在 Ubuntu 13.10 上使用 3930k 和 GTX690 就遇到了这种情况。再多的插值也无济于事; glm 的矩阵创建函数只是偶尔每隔几十帧随机飙升到 23-30 毫秒。 glm::translate() 和 glm::rotate() 都会发生。有些地方真的坏了。我检查了我的矩阵数据输入,在尖峰之前没有异常值。绝对是glm。 【参考方案1】:

这里有一些调试帮助,以免被埋没在 cmets 中:

记录每一帧的时间步长

当时间步长超过某个给定阈值且您确定足以导致“跳跃”时,暂停程序。

如果错误来自大时间步长,请跟踪哪些函数花费了多少时间,并查看是否有任何花费了不寻常的时间。

我。如果您有分析器,请在此处使用。

二。如果没有,记录每个函数之前和之后的时间并计算持续时间。在每一帧结束时总结这些时间步长,这样您仍然可以找到指示跳跃的总增量时间。

如果您将错误追溯到您无法控制的某个库/系统/其他调用,请确保您传递了这些函数(以及所有函数)的良好数据。

我。您是否可以在某处使用损坏的内存?

二。错误仅适用于旋转吗?平移/音阶呢?

三。如果您只是在尝试 OpenGL 的情况下运行程序,是否会发生此错误?例如,您的窗口可能是一个错误,您错过了一些更新调用或类似的微不足道的东西。

【讨论】:

我注意到,在使用 Microsoft 的注入调试器 (VC++ 2010) 运行程序时,如果数据类型不是,Visual Studio 每次输出到 std::cout 时都会抛出一个断点一个常量字符 *。如果我通过资源管理器独立运行程序,我没有任何问题,它会正确输出到控制台。这是否意味着我在某处内存管理不善?哪个可能导致口吃/断断续续?【参考方案2】:

这非常令人沮丧,但我重新启动了 Windows,所有问题都消失了。甚至调用 std::cout 会导致 Visual Studio 插入断点。

【讨论】:

【参考方案3】:

看起来glfwGetTime 使用QueryPerformanceCounter。这不是用于计时的正确 API,因为它测量的是“CPU 时间”而不是“Wall 时间”。它应该用于衡量代码性能,但仅此而已。您应该使用来自 Windows 多媒体计时器 API 的 timeGetTime()timeBeginPeriod()timeEndPeriod() 编写自己的计时器类:http://msdn.microsoft.com/en-us/library/windows/desktop/dd743609(v=vs.85).aspx

【讨论】:

它用于测量执行的 cpu“周期”数,并且当 CPU 以固定速率运行时,它是对实际经过时间的测量。然后 CPU 开始以可变速率运行,所以现在它以某个固定速率运行,就好像 CPU 以恒定速度运行一样。所以它应该很好地工作。在一些损坏的多核机器上曾经存在一些问题,它可能会在不同的核心上读取略有不同的值,因此会倒退,但现在这在实践中已经不是问题了。 很久以前我遇到了这个问题,所以你可能是正确的,它不再是一个问题,但是msdn.microsoft.com/en-us/library/windows/desktop/… 的页面表明有错误的 Bios/HAL 可能是归咎于结果不一致,所以它似乎仍然不是最安全的选择。

以上是关于GLM 不断提供不稳定的转换和旋转的主要内容,如果未能解决你的问题,请参考以下文章

使用 GLM(旋转)为 OpenGL 创建变换矩阵

glm 旋转无法正常工作

glm glx 旋转不起作用

GLSL 中的正常旋转

最大稳定极值区域(MSER)检测

glm 旋转不根据模型的新方向