Interpolating 2D angles

Started by
5 comments, last by Ozymandias42 17 years, 6 months ago
So, I've got two angles, "from" and "to". My object is at the "from" angle, and it wants to adjust itself 25% to the "to" angle, so for instance, if from=90 and to=0, the result should be 67.5. It's also a necessity that I take the shortest direction towards the to angle, i.e. result=67.5 instead of result=157.5. It's not too terribly difficult to implement this in C, but what I'm wondering is what's the fastest, shortest, or most elegant way to handle this question, assuming all angles are stored as a value betwee 0 and 359 (figure they're ints and ignore fractional values (in the actual game I use a much larger number than 359 as the maximum angle)). Here's a quick, potentially not great solution:

int averageAngles(int from, int to, float percent) {
   int dist;

   dist = to - from;
   if( dist > 180 )
       dist = dist - 360;
   else if( dist < -180)
       dist = - 360 - dist;
   dist = from + (int)(dist*percent);
   if( dist >= 360 )
         dist -= 360;
   else if( dist < 0 )
         dist += 360;
   return dist;
}
My question is, "is there a faster, better way?" I could get it down to one if statement by storing the sign of dist, but maybe I could let the compiler take better advantage of the hardware if I used max()s or min()s instead of if's? Or maybe there's just a plain better way? Thoughts? Suggestions?
Advertisement
Hi!

Does this function get called thousands of times per tick? Because unless that's the case then the best thing to do would be to do it whichever way you find it logical and just be done with it. I would say that your implementation is as good as any, after all you have only several very basic operations there...

When you've completed implementing most of the stuff you need, fire up a profiler and search for bottlenecks. That is the correct way to do optimalizations without wasting time and effort. I'd be very surprised if this function would be among the problematic ones though :)

Cheers!
Oh, I'm sure it's not going to be the most critical bottleneck by a wide margin, but I was just thinking about it and kept wondering if there were a better way of expressing what I wanted, and then I started thinking about what would be fastest, so it's mostly curiosity at this point.

But that's still always good advice. Premature optimization is the root of all evil, after all.
I answered a similar question recently (here), where the result was to find out the difference between two angles (and from there find out if it was clockwise or counter-clockwise). My solution used no if statements, and resulted in a delta of -180 to +179 (thus showing which direction to rotate to get the shortest rotation path). This could very easily be extended for your needs by multiplying the resulting number by the percentage you need. The full solution would then be:
float InterpolateAngles(int From, int To, float Percent){  return From + static_cast<float>(((To - From + 540) % 360) - 180) * Percent;}int InterpolateAngles(int From, int To, int Percent){  return From + ((((To - From + 540) % 360) - 180) * Percent + 50) / 100;}float InterpolateAngles(float From, float To, float Percent){  return From + (fmod((To - From + 540.0f), 360.0f) - 180.0f) * Percent;}

There's a few (untested) forms that take three different combinations of inputs/outputs.

[edit]various code fixes[/edit]
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
Why use angles at all? Why not just use vectors?
My point is that you seldom really actually need to know the angle, you probably don't show the value on screen anywhere. Often someone simply choses to represent something internally in polar coordinates because it seemed easy that way. In fact using vectors is often more elegant.
"In order to understand recursion, you must first understand recursion."
My website dedicated to sorting algorithms
I have to agree with IMacl there. Using vectors would be a lot easier to work with as well. Then worrying about angles.
Agony, I really like your ((((To - From + 540) % 360) - 180) solution. That works great. I was wondering whether I could use mod somehow, but couldn't figure out how to get it to work well with negatives. Good call.

Also, the reason I wasn't using a vector value for that particular value was that it represented the direction an object is facing, not the direction it is moving. I'm not really sure what the advantage of a vector would be in that particular situation. I suppose it'd be easier to, say, accelerate in the direction it's facing if the way it was facing was stored as a vector, but it makes rotations and comparisons more complicated. I certainly don't store velocity or position in polar, but what's the argument for storing facing as a vector?

This topic is closed to new replies.

Advertisement