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

Posted

技术标签:

【中文标题】将形状旋转到 1 到 2 弧度之间的任何位置都会重置其旋转【英文标题】:Rotating a shape to anywhere between 1 and 2 radians resets its rotation 【发布时间】:2021-08-25 12:49:48 【问题描述】:

我目前正在使用 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 有关,还是我的代码有问题?

【问题讨论】:

【参考方案1】:

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


具体来说,我犯了一个错误,与通过 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));

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

【讨论】:

以上是关于将形状旋转到 1 到 2 弧度之间的任何位置都会重置其旋转的主要内容,如果未能解决你的问题,请参考以下文章

HTML5 Canvas 中旋转矩形内的鼠标位置

根据鼠标的位置旋转我的形状的角度。

OCR 旋转图像

两点之间的方位角+地球曲率问题

iPhone - 核心运动旋转率

如何在 C# 中旋转二维对象