简体   繁体   English

四边形的二维旋转

[英]2D rotation of a quad

I am working on a basic simulation program using C++ and I have a renderer that uses OpenGL.我正在使用 C++ 开发一个基本模拟程序,并且我有一个使用 OpenGL 的渲染器。 I am rendering quads on the screen which have a dynamic location in the simulation.我正在屏幕上渲染在模拟中具有动态位置的四边形。 My goal is to change the orientation of the quad when it is moving in the simulation.我的目标是在模拟中移动四边形时改变它的方向。 For each quad, I have a variable (m_Rotation) which holds the current rotation of it and I calculate the required rotation using trigonometry and put the value in a variable (m_ProjectedRotation).对于每个四边形,我有一个变量 (m_Rotation) 保存它的当前旋转,我使用三角函数计算所需的旋转并将值放入变量 (m_ProjectedRotation)。 In the render loop, I use the following code to change the orientation in the movement:在渲染循环中,我使用以下代码来更改运动的方向:

if(abs(m_ProjectedRotation - m_Rotation)>5.0f)
{   
    if ((360.0f - m_Rotation + m_ProjectedRotation) > (m_ProjectedRotation - m_Rotation))
    {
        m_Rotation += 5.0f;
        if (m_Rotation > 360)
        {
              m_Rotation = fmod(m_Rotation, 360);
        }
    }
    else 
    {
        m_Rotation -= 5.0f;
    }
                
}

I want the quad to rotate itself according to the closest angle( eg if the current angle is 330, and the destination angle is 30, the quad should increase its angle until it reaches 30 not decreasing the angle since it reaches 30. Because it has a smaller angle to rotate ).我希望四边形根据最接近的角度自行旋转(例如,如果当前角度为 330,目标角度为 30,则四边形应增加其角度直到达到 30,而不是自达到 30 后减少角度。因为它有较小的旋转角度)。 In some conditions, my quad rotates itself counterclockwise even tough the clockwise rotation has shorter rotation and vice versa.在某些情况下,我的四边形会逆时针旋转,即使顺时针旋转的旋转时间较短,反之亦然。 I believe the condition for rotation:我相信轮换的条件:

(360.0f - m_Rotation + m_ProjectedRotation) > (m_ProjectedRotation - m_Rotation)

should be something different to show the required behavior.应该是不同的东西来显示所需的行为。 However, I couldn't figure it out.然而,我想不通。 How should I update this code to get what I want?我应该如何更新此代码以获得我想要的?

I believe the correct solution should be as follows:我认为正确的解决方案应该如下:

Let's call the two angles from and to .让我们将这两个角度称为fromto I assume both are in positive degrees as per your question.根据你的问题,我认为两者都是积极的。 There are two cases:有两种情况:

  • the absolute distance |to - from| |to - from|的绝对距离is less than 180.小于 180。
    This means there is less degrees to travel by to - from than in the other direction, and that is the way you should choose.这意味着往返的to - from比另一个方向要少,就是您应该选择的方式。
    In this case, you should rotate by sign(to-from) * deltaRotation , where sign(x) = 1 if x > 0 and -1 otherwise.在这种情况下,您应该按sign(to-from) * deltaRotation ,其中如果 x > 0,则sign(x) = 1,否则为 -1。 To see the need of the sign function, look at the following 2 examples, where |to - from|要查看符号 function 的必要性,请查看以下 2 个示例,其中|to - from| < 180: < 180:
    • from = 10, to = 20. to - from = 10 > 0, so you should increase rotation. from = 10, to = 20. to - from = 10 > 0,所以你应该增加旋转。
    • from = 20, to = 10. to - from = -10 < 0, you should decrease rotation.从 = 20,到 = 10。到 - 从 = -10 < 0,您应该减少旋转。
  • |to - from| is more than 180. In this case, the direction should be the inverse, and you should rotate by - sign(to-form) * deltaRotation , note the minus sign.大于 180。在这种情况下,方向应该是相反的,你应该旋转- sign(to-form) * deltaRotation ,注意减号。 You could also express this as sign(from-to) * deltaRotation , swapping from and to , but I left them as before for explicitness.您也可以将其表示为sign(from-to) * deltaRotation ,交换fromto ,但为了明确起见,我像以前一样保留了它们。
    • from = 310, to = 10. Then, to - from = -300 < 0, you should increase rotation (Formally, -sign(to-from) = -sign(-300) = -(-1) = 1) from = 310,to = 10。然后,to - from = -300 < 0,你应该增加旋转(正式地,-sign(to-from) = -sign(-300) = -(-1) = 1)
    • from = 10, to = 310. Then, to - from = 300 > 0, you should decrease rotation (Formally, -sign(to-from) = -sign(300) = -1)从 = 10,到 = 310。然后,到 - 从 = 300 > 0,你应该减少旋转(正式地,-sign(to-from) = -sign(300) = -1)

Writing this in C++ you can encapsulate this logic in such a function:在 C++ 中编写此代码,您可以将此逻辑封装在这样的 function 中:

int shorterRotationSign(float from, float to) {
    if(fabs(to - from) <= 180) {
        return to - from > 0 ? 1 : -1;
    }
    return to - from > 0 ? -1 : 1;
}

Which you will use like this:您将像这样使用它:

m_Rotation += 5.0f * shorterRotationSign(m_Rotation, m_ProjectedRotation);

m_Rotation = fmod(m_Rotation + 360, 360);

The goal of the last line is to normalize negative angles and ones greater than 360.最后一行的目标是归一化负角和大于 360 的角。

(IMO This is more of a mathematical question than one about opengl.) (IMO 这更像是一个数学问题,而不是关于 opengl 的问题。)

I would do something like that:我会做这样的事情:

auto diff = abs(m_ProjectedRotation - m_Rotation);
if(diff > 5.0f)
{   
    diff = fmod(diff, 360.0f); 
    auto should_rotate_forward = (diff > 180.0f) ^ (m_ProjectedRotation > m_Rotation);
    auto offset = 360.0f + 5.0f * (should_rotate_forward ? 1.0f : -1.0f);
    m_Rotation = fmod(m_Rotation + offset, 360.0f);            
}

diff is the absolute angle of your rotation. diff是您旋转的绝对角度。 You then make it in a [0;然后你把它放在 [0; 360) range by doing diff = fmod(diff, 360.0f) . 360) 范围通过执行diff = fmod(diff, 360.0f)

should_rotate_forward determines whether you should decrease or increase the current angle. should_rotate_forward决定是否应该减小或增大当前角度。 Note the ^ is a XOR operation注意^是 XOR 操作

offset is basically either -5.0 or 5.0 depending on condition, but there's also +360.0f so that if for example m_Rotation == 1.0 and offset == -5.0 so fmod(m_Rotation + offset, 360.0f) would be -4.0 while you want 356.0 , so you add full 360 rotation and after fmod everything is positive and in [0; offset基本上是-5.05.0 ,具体取决于条件,但也有+360.0f因此如果例如m_Rotation == 1.0offset == -5.0那么fmod(m_Rotation + offset, 360.0f)将是-4.0而你想要356.0 ,因此您添加完整的 360 度旋转,并且在fmod之后一切都是正数并且在 [0; 360) range 360) 范围

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM