Search code examples
c++rotationinterpolationangle

Logical issue in interpolation between two angles?


What I'm trying to do is make an object in 2D that is rotated a certain degrees, A degrees, for example, rotate to face the mouse, whose direction FROM that object is B degrees. This is in openGl.

I'm already able to instantly rotate the object, using the glRotatef function, but what I wan't to do is to be able to control the rotation over a certain number of seconds.

I'm using two methods which either increase, or decrease the rotation:

    void GameObject::increaseRot(int millis) {
        rotation += getRotDeg(millis);
    }

    void GameObject::decreaseRot(int millis) {
        rotation -= getRotDeg(millis);
    }

    double GameObject::getRotDeg(int millis) {
        double rot = 360 / this->rotSpeed;
        rot = rot * millis / 1000.0;
        return rot;
    }

Millis comes from a timer which works properly, and so I can cause an object to rotate at a speed of 360 degrees every rotSpeed seconds.

Edit: I've found a solution on the internet, that seems to mostly work. Using the formula of that solution with my own code, the code is

    shortest_angle=((((end - start) % 360) + 540) % 360) - 180;

    /*  check which way to rotate
     *  this part of the code appears to work fine, all it does is
     *    rotate a certain number of degrees, it's my code that I've been
     *   using the whole time
     */
    if(rotateA < 0)
        game.getPlayer().decreaseRot(deltaT);
    else if(rotateA > 0)
        game.getPlayer().increaseRot(deltaT);

However, the code still takes the longer route at certain values, and I can't figure out why . . .

The value I've noticed this happening are:

    45 trying for 135
    225 trying for 315
    315 trying for 45

These are approximate values of course, any values around those areas will screw up. I've been thinking that it's something to do with the limits 90, 180, 270 and 360/0, but I can't figure out what the actual problem is.


Solution

  • I have found and worked out the solution to this question, for anyone else that might also be having the same problem.

    Using the code from "user151496", Rotation Interpolation

          shortest_angle=((((end - start) % 360) + 540) % 360) - 180;
          return shortest_angle * amount;
    

    You can change it to apply your own custom rotation speed as I have using functions such as

        if(rotateA < 0 && rotateA >= -180)
            game.getPlayer().decreaseRot(deltaT);
        else if (rotateA < 0 && rotateA <= -180)    //for the crossing of the boundary
            game.getPlayer().increaseRot(deltaT);
        else if(rotateA > 0 && rotateA <= 180)
            game.getPlayer().increaseRot(deltaT);
        else if(rotateA > 0 && rotateA >= 180)
            game.getPlayer().decreaseRot(deltaT);   //for the crossing of the boundary
    

    All this ^ does is check whether the shortest_angle is positive or negative (rotateA). Then it either rotates clockwise (decreaseRot) or counterclockwise(increaseRot) accordingly. Note, however, the two extra lines, checking the -180 and 180 degrees conditions. These are necessary - I find it hard to explain numerically but it has to do with crossing the 0/360 degrees line.

    If you dont have those extra conditions, the rotation will rotate on the larger angle whenever you have to cross such a boundary.