2D rotation interpolation

BlitzMax Forums/BlitzMax Programming/2D rotation interpolation

ragtag(Posted 2006) [#1]
I'm trying to figure out a nice way to interpolate rotation without it flipping. I have a working code for it, but just have this nudging feeling that there is a better way to do it.

Here is what I have now.

	Method AngleBetween:Float(  x1:Float, y1:Float, x2:Float, y2:Float  )
		Local xd:Float = (x1-x2)
		Local yd:Float = (y1-y2)
		Local m:Float = 90
		If xd < 0 Then m = 270
		Local Angle:Float = ATan(yd/xd) + m
		If Angle = "nan" Then Return 0 Else Return Angle
	End Method
	
 ' And elsewhere in the code

 	Method Update( Rotation:Int = 0)
		If Rotation And (Abs(Goal-Value)) > 180 Then
			If Value > 360 Then Value:- 360
			If Value < 0 Then Value:+ 360
			If Goal > 180 Then Goal:- 360 Else Goal:+ 360
		End If
		Local Distance:Float = Goal - Value
		Local Acceleration:Float = (Distance - Vel*Lag)*2/(Lag*Lag)
		Vel:+ Acceleration
		Value:+ Vel
	End Method



The Rotation input variable on the second method is just a flag to tell it if rotation is being interpolated, so that it can do some stuff to avoid flipping. The Update method take any number and moves it towards a goal with a physics like lag.

Is there a cleaner way to do this? The "If Angle = "nan" feels a bit hacky, and the whole thing that flips the rotation with lots of If's in the second Method too.

Cheers,

Ragnar


assari(Posted 2006) [#2]
Check out these codes in the code archives


ragtag(Posted 2006) [#3]
Thanks for the pointer. The code samples there are basically doing the same thing, subtracting or adding 360 when the angle goes beyond 360 or under 0. Guess that's the way to do it then. :-)

Ragnar


TomToad(Posted 2006) [#4]
use ATan2(). It gives the angle from -180 to 180 with 0 pointing right. Just add 360 if the result is less than 0
Angle = ATan2(yd,xd) 'notice that yd is first parameter

'      |-90
'      |
' -180 |   0
'------+------
'  180 |     0
'      |
'      |90

If Angle < 0 then Angle :+ 360

'      |270
'      |
' 180  |  360
'------+------
'      |     0
'      |
'      |90



Haramanai(Posted 2006) [#5]
It's better to keep the original output of the ATan2 cause you will utomatically know if it's pointing upwards or downwards by signe ( - , + ). This will help you better to find which way (left or right) you have to turn to get at a desired angle.


The r0nin(Posted 2006) [#6]
Hmmm. What would I do (mathematically) if I wanted the Atan2() output to generate 0 for screen-up (North) with positive angles being screen-right (East) and negative angles being screen-left (West)?


TomToad(Posted 2006) [#7]
Haramanai: I usually keep the ATan2 values, simply because that's the way I've always dealt with polar coordinates. But SetRotation expects 0-360, so you will need to correct for that.

The r0nin:
Angle = Atan2(yd,xd) + 90
If Angle > 180 then Angle :- 360



Haramanai(Posted 2006) [#8]
TomToad you are not right about that.
You can use negative values for the SetAngel.
Check out this :
Strict

Graphics 640 , 480
While Not KeyDown(KEY_ESCAPE)
	Cls
	
	Local dx = MouseX() - 320
	Local dy = MouseY() - 240
	Local angle = ATan2( dy , dx )
	
	SetRotation angle
	DrawLine 320 , 240 , 340 , 240
	
	SetRotation 0
	DrawText angle , 10 , 10
	
	Flip
Wend


Edit: Funny. We posted allmost the same example to defferent topics in the forum.


TomToad(Posted 2006) [#9]
From the docs
Function SetRotation( rotation# )
Description Set current rotation.
Information rotation is given in degrees and should be in the range 0 to 360.


It might work now, but we can't rely on it to always work like that.


The r0nin(Posted 2006) [#10]
OH. Simple (duh!). Thanks, TomToad!