Rotation interpolation

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
pippy2
Posts: 5
Joined: Thu Mar 06, 2008 3:09 am

Rotation interpolation

Post by pippy2 »

I have two rotations, a target and a current(old) rotation vector. I need to animate a smooth transition between the two.

How do I get a rotation that is between the two vector3fs?
night_hawk
Posts: 153
Joined: Mon Mar 03, 2008 8:42 am
Location: Suceava - Romania
Contact:

Post by night_hawk »

Code: Select all

vector3df base,target;
irr::f32 speed;
... //assign them here

vector3df move=(target-base).normalise();

base+=move*speed*delta; //delta is a value to make it framerate independent
//assign base to your node via ->setRotation()
This is only the simple version. The longer version is to also check if it's the shortest rotation path. :D
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

You mean rotated vecotr, or rotation vector?. If you have two rotations, it's best to interpolate by quaternions, using the slerp() method.
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

This is an interesting thread, I'd like to know more about slerp() as I'm studying timelines and keyframe animation.

Specifically, I'd like to know how easing-in and easing-out is implemented in combination with slerp().
Image
pippy2
Posts: 5
Joined: Thu Mar 06, 2008 3:09 am

Post by pippy2 »

night_hawk: thanks heaps for your code =D

I would love a method that checked for the shortest path. for example if the original X was at 20, and the target X was at 270 it would be quicker to go down instead of up...

My code for doing this looks like someone threw it up, and it still doesn't work right, at certain angles it goes the wrong way.
morris
Posts: 36
Joined: Tue Jul 10, 2007 10:10 am

Post by morris »

the "shortest" path is easily defined. consider a rotation around, lets say, the Y axis. any rotation R bigger than 180° can be described as "long", and the shorter path is -(360°-R). so, after calculating your rotation vector [edit: but BEFORE normalizing it], check for each axis if the rotation is bigger than 180° (and maybe also -180°) and set the shorter angle if yes [edit: or just change the sign of that axis].

edit:
in fact, it IS a problem if you have rotations on all axes - you really should therefore stick to quaternions' slerp(). otherwise you'll have to handle some special cases (for example when your object makes a looping) as the rotation vector will not be returned continously, but there will be some "jumps".
pippy2
Posts: 5
Joined: Thu Mar 06, 2008 3:09 am

Post by pippy2 »

Thanks morris. I tried to work out the interpolation using this code:

Code: Select all

core::vector3df rotinterpol(const core::vector3df &actualCamera, const core::vector3df &orginalRotation, const u32 &interpolation){
				
	core::vector3df base = actualCamera;
	core::vector3df move = (actualCamera-orginalRotation);

	if(move.Y > 180)
		move.Y = -move.Y;
	if(move.Y < -180)
		move.Y = -move.Y;
	if(move.X > 180)
		move.X = -move.X;
	if(move.X < -180)
		move.X = -move.X;
	if(move.Z > 180)
		move.Z = -move.Z;
	if(move.Z < -180)
		move.Z = -move.Z;

	move =  move.normalize ();
	base -= move * interpolation; 
	return base;
};
as you can tell it didn't work. I'll read up more about slerp now. I still don't understand exactly what it does.
pippy2
Posts: 5
Joined: Thu Mar 06, 2008 3:09 am

Post by pippy2 »

I got closer with the previous method than this one:

Code: Select all

core::vector3df rotinterpol(const core::vector3df &actualCamera, const core::vector3df &orginalRotation, const f32 &interpolation){
	core::quaternion tmp;
	tmp.slerp( core::quaternion(actualCamera), core::quaternion(orginalRotation),  interpolation);

	core::vector3df ret;
	tmp.toEuler (ret);
 	return ret;
};
It's most likely not working because I don't really understand what the slerp code does. The code looks like someone threw up :/
xDan
Competition winner
Posts: 673
Joined: Thu Mar 30, 2006 1:23 pm
Location: UK
Contact:

Post by xDan »

For some strange reason the quaternion classes take radians... Or is it: for some strange reason scene nodes use degrees?

Code: Select all

core::vector3df rotinterpol(const core::vector3df &actualCamera, const core::vector3df &orginalRotation, const f32 &interpolation){
	core::quaternion tmp;
	tmp.slerp( core::quaternion(actualCamera * core::DEGTORAD), core::quaternion(orginalRotation * core::DEGTORAD),  interpolation);

	core::vector3df ret;
	tmp.toEuler (ret);
 	return ret * core::RADTODEG;
};
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

All methods should explicitly state which type they take in their API docs. But yes, there are methods which take one or the other, so you have to be careful.
pippy2
Posts: 5
Joined: Thu Mar 06, 2008 3:09 am

Post by pippy2 »

ah, thanks xDan!

Edit: For some reason it doesn't interpolate the Z coordinate. I'll look into it more
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

xDan wrote:For some strange reason the quaternion classes take radians... Or is it: for some strange reason scene nodes use degrees?

Code: Select all

core::vector3df rotinterpol(const core::vector3df &actualCamera, const core::vector3df &orginalRotation, const f32 &interpolation){
	core::quaternion tmp;
	tmp.slerp( core::quaternion(actualCamera * core::DEGTORAD), core::quaternion(orginalRotation * core::DEGTORAD),  interpolation);

	core::vector3df ret;
	tmp.toEuler (ret);
 	return ret * core::RADTODEG;
};
EDIT:
I am curious as to why you are passing 'interpolation' as a constant reference. Correct me if I am wrong, but if you have SSE/SSE2/SEE3 they have 128-bit registers which makes the passing of float/double values by reference unneeded.

Otherwise, that is a good code snippet right there.
Last edited by Halifax on Sat Mar 15, 2008 4:27 pm, edited 1 time in total.
TheQuestion = 2B || !2B
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

MMX is for integers. :P
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Halifax
Posts: 1424
Joined: Sun Apr 29, 2007 10:40 pm
Location: $9D95

Post by Halifax »

BlindSide wrote:MMX is for integers. :P
Hmm, thanks for specifying that. I always wondered why my machine supported MMX and SSE. :lol: Ah well, I will edit that post. (MMX removed).
TheQuestion = 2B || !2B
Post Reply