Wednesday, September 19, 2018

2d vector flips during rotation


I have a 2d game (C++ and SDL) and I want the player object rotate to follow the mouse. The player object and the mouse location are both stored in 2d vectors.


In order to have the player's rotation look nice, I applied this lerp code between the "current" and "future" angle.


This is the function i'm using below, it should be straightforward:


void Vector2D_LerpAngle(const Vector2D& future, const float& dt, Vector2D& current)
{
float a = 0.0f, b = 0.0f, c=0.0f;

Vector2D_GetAngleDegrees(future, a);

Vector2D_GetAngleDegrees(current, b);

c = (a*t + b * (1.0 - t) - b);

Vector2D_RotateByDegrees(c, current);
}

This actually works great - until the player rotates past 0 degrees. Then, it suddenly rotates in the opposite direction for almost an entire circle.


The only way I've been able to find to fix this is adding logic to catch the special case of being within 0-360 degrees, but to do that properly I'm going to have to take the velocity of the mouse into account, and that's just going to be a pain. I feel like I'm probably missing something obvious here or else I'm doomed to failure with this particular method.


edit:



It turns out lerping the vectors themselves rather than the angle works. I should have just trusted the math.


void Vector2D_Lerp(const Vector2D& future, const float& t, Vector2D& current)
{
current = future*t + current*(1.0f - t);
}

Answer



Rather than fiddling with angles, you can use a cross-product to know in which direction you should rotate. Don't be scared by the theory dump : it's actually pretty simple to use!


Let C be current and F be future. They are both 3-dimensional vectors, with z = 0. Then the cross-product P = C×F has the following properties:



  • Px = 0 and Py = 0;


  • Pz = CxFy - CyFx, which is rather easy to compute, but also:

  • Pz = ||C||⋅||F||⋅sin θ, θ being the smaller directed angle from C to F;

  • sin θ and θ have the same sign, unless θ = 180°.


In short: compute (C×F)z, look at its sign:



  • < 0, you need to turn right

  • > 0, you need to turn left

  • = 0, you're either dead centered towards your goal, or facing exactly away.



In the zero case, you can know which situation you're in with the dot product, d = CxFx + CyFy:



  • If d > 0, the vectors face the same direction;

  • If d < 0, the vectors face away from each other;

  • If d = 0, the vectors are orthogonal (but we don't care here).


I hope I managed to be clear enough :)


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...