将形状旋转到 1 到 2 弧度之间的任何位置会重置其旋转

Rotating a shape to anywhere between 1 and 2 radians resets its rotation

我目前正在使用 GLM 在 OpenGL 中转换形状。但是,当形状的旋转介于 1 到 2 弧度之间时,表示旋转的矩阵值将设置回它们在单位矩阵中的值。我目前正在将模型矩阵输出到控制台,这有助于找出它转回 0 弧度旋转的确切时刻。这是:

抱歉,如果它难以理解,我已经尝试对其进行注释,因为否则看起来会很烦人。有需要的直接上图link

控制台中每行的第一个值是作为单个值的旋转,以弧度表示。然后,输出形状的模型矩阵。

上传它的视频很烦人,但我相信你可以想象它 - 它只是一个正常旋转一段时间的形状,直到旋转达到一个弧度,此时它会重置为正常旋转。然后,当它达到两个弧度时,它又恢复正常,就好像从来没有问题一样。

变形相关的代码如下:

// NOTE: the variables 'active_translation, active_rotation, and active_scaling' are the values the user gives to translate, rotate, and scale the shape
// In this case, 'active_rotation' is equal to ~0.02 (1 degree in radians) every frame

void defshape::apply_transformations() {
    // Create an identity matrix to store the applied transformations
    glm::mat4 applied_transformation = glm::mat4(1.0f);

    // Add the active translation to the stored transformations variable
    applied_transformation = glm::translate(applied_transformation, active_translation);

    // Apply the rotation to the mat4. For the sake of this example, I've only showed the Z axis line to simplify it as it's the only one being affected.
    applied_transformation = glm::rotate(applied_transformation, active_rotation.z, glm::vec3(0, 0, 1));

    // Add the active scale to the stored transformations variable
    applied_transformation = glm::scale(applied_transformation, active_scaling);

    // Apply these changes to the renderer by setting its model matrix and then updating it
    renderer_handle->model_matrix = applied_transformation;
    renderer_handle->update_renderer();

    // Reset the translation of the model matrix back to 0
    // This step ensures that the object rotates around its local origin, rather than the world space origin
    applied_transformation = glm::translate(applied_transformation, glm::vec3(0.0f));

    // Then apply this change to the renderer's model matrix
    renderer_handle->model_matrix = applied_transformation;
    renderer_handle->update_renderer();
}

这可能与 GLM 有关,还是我的代码有问题?

已解决 - 这个问题与我的项目特定的代码块有关,这可能就是它如此独特的原因。


具体来说,我犯了一个关于通过 glm 旋转时影响哪些轴的错误。我第一次编码的方式是这样的:

// Variable to store the affected rotation axes
glm::vec3 _active_rotation_axes = glm::vec3(0, 0, 0);

// Get the affected axes for rotation
// 'active_rotation' stores the rotation values for each axis
_active_rotation_axes.x = (active_rotation.x != 0) ? 1 : 0;
_active_rotation_axes.y = (active_rotation.y != 0) ? 1 : 0;
_active_rotation_axes.z = (active_rotation.z != 0) ? 1 : 0;

// Keep in mind the above code is partly pseudocode, as I have simplified it heavily and typed it directly into the answer.

然后变量_active_rotation_axes被这样使用:

if (_active_rotation_axes.x != 0) applied_transformation = glm::rotate(applied_transformation, active_rotation.x, glm::vec3(_active_rotation_axes.x, 0, 0));
if (_active_rotation_axes.y != 0) applied_transformation = glm::rotate(applied_transformation, active_rotation.y, glm::vec3(0, _active_rotation_axes.y, 0));
if (_active_rotation_axes.z != 0) applied_transformation = glm::rotate(applied_transformation, active_rotation.z, glm::vec3(0, 0, _active_rotation_axes.z));

这导致了我遇到的问题, 虽然我仍然不知道确切原因。

无论如何,最后我要做的就是删除第一个代码块,并将第二个代码块更改为以下代码,它直接检查 active_rotation 而不是现在不存在的变量 _active_rotation_axes:

if (active_rotation.x != 0) applied_transformation = glm::rotate(applied_transformation, active_rotation.x, glm::vec3(1, 0, 0));
if (active_rotation.y != 0) applied_transformation = glm::rotate(applied_transformation, active_rotation.y, glm::vec3(0, 1, 0));
if (active_rotation.z != 0) applied_transformation = glm::rotate(applied_transformation, active_rotation.z, glm::vec3(0, 0, 1));

真的,我应该从一开始就这样做,因为它明显更加高效和简单。